diff --git a/client/trino-cli/src/test/java/io/trino/cli/TestInsecureQueryRunner.java b/client/trino-cli/src/test/java/io/trino/cli/TestInsecureQueryRunner.java index 8a918985ace2e..1cf44de01d79f 100644 --- a/client/trino-cli/src/test/java/io/trino/cli/TestInsecureQueryRunner.java +++ b/client/trino-cli/src/test/java/io/trino/cli/TestInsecureQueryRunner.java @@ -57,6 +57,7 @@ public void teardown() throws Exception { server.close(); + server = null; } @Test diff --git a/client/trino-cli/src/test/java/io/trino/cli/TestQueryRunner.java b/client/trino-cli/src/test/java/io/trino/cli/TestQueryRunner.java index e7acc3e0fc227..6fe10041e06ae 100644 --- a/client/trino-cli/src/test/java/io/trino/cli/TestQueryRunner.java +++ b/client/trino-cli/src/test/java/io/trino/cli/TestQueryRunner.java @@ -67,6 +67,7 @@ public void teardown() throws IOException { server.close(); + server = null; } @Test diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcConnection.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcConnection.java index 520d65528ffdc..b401417e6bdf4 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcConnection.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcConnection.java @@ -116,6 +116,7 @@ public void tearDown() closeAll( server, executor::shutdownNow); + server = null; } @Test diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcPreparedStatement.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcPreparedStatement.java index 24153174396a8..919c27bd741b3 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcPreparedStatement.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcPreparedStatement.java @@ -107,6 +107,7 @@ public void tearDown() throws Exception { server.close(); + server = null; } @Test diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcResultSet.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcResultSet.java index 93ca43d2b0a86..95c3378ed18cb 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcResultSet.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcResultSet.java @@ -49,6 +49,7 @@ public void tearDownServer() throws Exception { server.close(); + server = null; } @Override diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcStatement.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcStatement.java index a41549450f6e1..26acf253cf6d1 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcStatement.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcStatement.java @@ -75,6 +75,7 @@ public void tearDown() closeAll( server, executor::shutdownNow); + server = null; } @Test(timeOut = 60_000) diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcVendorCompatibility.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcVendorCompatibility.java index fb56a1500849f..9a77450e05dfb 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcVendorCompatibility.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcVendorCompatibility.java @@ -14,10 +14,10 @@ package io.trino.jdbc; import com.google.common.collect.ImmutableList; -import com.google.common.io.Closer; import io.airlift.log.Logger; import io.airlift.log.Logging; import io.trino.server.testing.TestingTrinoServer; +import io.trino.util.AutoCloseableCloser; import oracle.jdbc.OracleType; import org.testcontainers.containers.OracleContainer; import org.testcontainers.containers.PostgreSQLContainer; @@ -88,16 +88,34 @@ public void setupServer() Logging.initialize(); log = Logger.get(TestJdbcVendorCompatibility.class); server = TestingTrinoServer.create(); - referenceDrivers = ImmutableList.of(new PostgresqlReferenceDriver(), new OracleReferenceDriver()); + + // Capture resources as soon as they are allocated. Ensure all allocate resources are cleaned up even if e.g. the last one fails to start. + referenceDrivers = new ArrayList<>(); + referenceDrivers.add(new PostgresqlReferenceDriver()); + referenceDrivers.add(new OracleReferenceDriver()); } @AfterClass(alwaysRun = true) public void tearDownServer() throws Exception { - try (Closer closer = Closer.create()) { - referenceDrivers.forEach(closer::register); - closer.register(server); + try (AutoCloseableCloser closer = AutoCloseableCloser.create()) { + if (referenceDrivers != null) { + referenceDrivers.forEach(closer::register); + referenceDrivers.clear(); + } + if (server != null) { + closer.register(server); + server = null; + } + if (connection != null) { + closer.register(connection); + connection = null; + } + if (statement != null) { + closer.register(statement); + statement = null; + } } } @@ -116,8 +134,14 @@ public void setUp() public void tearDown() throws Exception { - statement.close(); - connection.close(); + if (statement != null) { + statement.close(); + statement = null; + } + if (connection != null) { + connection.close(); + connection = null; + } for (ReferenceDriver driver : referenceDrivers) { try { driver.tearDown(); diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcWarnings.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcWarnings.java index daba7f34344d4..99996dea46975 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcWarnings.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestJdbcWarnings.java @@ -100,6 +100,7 @@ public void tearDownServer() throws Exception { server.close(); + server = null; } @SuppressWarnings("JDBCResourceOpenedButNotSafelyClosed") @@ -117,8 +118,11 @@ public void teardown() throws Exception { executor.shutdownNow(); + executor = null; statement.close(); + statement = null; connection.close(); + connection = null; } @Test diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestProgressMonitor.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestProgressMonitor.java index bbe302edff5d2..208a17a1bc835 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestProgressMonitor.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestProgressMonitor.java @@ -65,6 +65,7 @@ public void teardown() throws IOException { server.close(); + server = null; } private List createResults() diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDatabaseMetaData.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDatabaseMetaData.java index c5c9517af423a..0f7f8853895f2 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDatabaseMetaData.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDatabaseMetaData.java @@ -166,6 +166,7 @@ public void tearDown() throws Exception { connection.close(); + connection = null; } @Test diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriver.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriver.java index ed4ccac497074..8a33f500a5f2e 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriver.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriver.java @@ -130,6 +130,7 @@ public void teardown() executorService.shutdownNow(); executorService = null; server.close(); + server = null; } @Test diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriverAuth.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriverAuth.java index bf6184f72fa6b..42e8f897974bb 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriverAuth.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriverAuth.java @@ -93,6 +93,7 @@ public void teardown() throws Exception { server.close(); + server = null; } @Test diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriverImpersonateUser.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriverImpersonateUser.java index acb7e919e2f87..78b559a05db60 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriverImpersonateUser.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDriverImpersonateUser.java @@ -79,6 +79,7 @@ public void teardown() throws Exception { server.close(); + server = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/cost/TestStatsCalculator.java b/core/trino-main/src/test/java/io/trino/cost/TestStatsCalculator.java index 1aaa56936fc2b..70ea1fe107681 100644 --- a/core/trino-main/src/test/java/io/trino/cost/TestStatsCalculator.java +++ b/core/trino-main/src/test/java/io/trino/cost/TestStatsCalculator.java @@ -22,6 +22,8 @@ import io.trino.sql.planner.assertions.PlanMatchPattern; import io.trino.sql.planner.plan.TableScanNode; import io.trino.testing.LocalQueryRunner; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import static io.trino.sql.planner.LogicalPlanner.Stage.OPTIMIZED_AND_VALIDATED; @@ -32,11 +34,12 @@ public class TestStatsCalculator { - private final LocalQueryRunner queryRunner; + private LocalQueryRunner queryRunner; - public TestStatsCalculator() + @BeforeClass + public void setUp() { - this.queryRunner = LocalQueryRunner.create(testSessionBuilder() + queryRunner = LocalQueryRunner.create(testSessionBuilder() .setCatalog(TEST_CATALOG_NAME) .setSchema("tiny") .setSystemProperty("task_concurrency", "1") // these tests don't handle exchanges from local parallel @@ -48,6 +51,13 @@ public TestStatsCalculator() ImmutableMap.of()); } + @AfterClass(alwaysRun = true) + public void tearDown() + { + queryRunner.close(); + queryRunner = null; + } + @Test public void testStatsCalculatorUsesLayout() { diff --git a/core/trino-main/src/test/java/io/trino/execution/BaseDataDefinitionTaskTest.java b/core/trino-main/src/test/java/io/trino/execution/BaseDataDefinitionTaskTest.java index 16adc0e317354..e0aa0d131b40f 100644 --- a/core/trino-main/src/test/java/io/trino/execution/BaseDataDefinitionTaskTest.java +++ b/core/trino-main/src/test/java/io/trino/execution/BaseDataDefinitionTaskTest.java @@ -128,7 +128,14 @@ public void tearDown() { if (queryRunner != null) { queryRunner.close(); + queryRunner = null; } + testSession = null; + metadata = null; + plannerContext = null; + materializedViewPropertyManager = null; + transactionManager = null; + queryStateMachine = null; } protected static QualifiedObjectName qualifiedObjectName(String objectName) diff --git a/core/trino-main/src/test/java/io/trino/execution/TestCallTask.java b/core/trino-main/src/test/java/io/trino/execution/TestCallTask.java index 6925195542054..cbca6ddbddbc5 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestCallTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestCallTask.java @@ -82,6 +82,7 @@ public void close() { if (queryRunner != null) { queryRunner.close(); + queryRunner = null; } executor.shutdownNow(); executor = null; diff --git a/core/trino-main/src/test/java/io/trino/execution/TestCreateMaterializedViewTask.java b/core/trino-main/src/test/java/io/trino/execution/TestCreateMaterializedViewTask.java index 5a5500b3afd23..8a51bfd141eb8 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestCreateMaterializedViewTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestCreateMaterializedViewTask.java @@ -155,6 +155,15 @@ public void tearDown() if (queryRunner != null) { queryRunner.close(); } + testSession = null; + metadata = null; + plannerContext = null; + transactionManager = null; + parser = null; + queryStateMachine = null; + analyzerFactory = null; + materializedViewPropertyManager = null; + queryRunner = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/execution/TestCreateTableTask.java b/core/trino-main/src/test/java/io/trino/execution/TestCreateTableTask.java index f9ff4dd52ed50..619a69f7609a8 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestCreateTableTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestCreateTableTask.java @@ -142,6 +142,12 @@ public void tearDown() if (queryRunner != null) { queryRunner.close(); } + queryRunner = null; + transactionManager = null; + tablePropertyManager = null; + columnPropertyManager = null; + metadata = null; + plannerContext = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/execution/TestMemoryRevokingScheduler.java b/core/trino-main/src/test/java/io/trino/execution/TestMemoryRevokingScheduler.java index 03637a5151d88..8b9986c4e5085 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestMemoryRevokingScheduler.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestMemoryRevokingScheduler.java @@ -71,10 +71,11 @@ public class TestMemoryRevokingScheduler private final SpillSpaceTracker spillSpaceTracker = new SpillSpaceTracker(DataSize.of(10, GIGABYTE)); private final Map queryContexts = new HashMap<>(); + private MemoryPool memoryPool; + private TaskExecutor taskExecutor; private ScheduledExecutorService executor; private ScheduledExecutorService scheduledExecutor; private SqlTaskExecutionFactory sqlTaskExecutionFactory; - private MemoryPool memoryPool; private Set allOperatorContexts; @@ -83,7 +84,7 @@ public void setUp() { memoryPool = new MemoryPool(DataSize.ofBytes(10)); - TaskExecutor taskExecutor = new TaskExecutor(8, 16, 3, 4, Ticker.systemTicker()); + taskExecutor = new TaskExecutor(8, 16, 3, 4, Ticker.systemTicker()); taskExecutor.start(); // Must be single threaded @@ -107,8 +108,12 @@ public void tearDown() { queryContexts.clear(); memoryPool = null; + taskExecutor.stop(); + taskExecutor = null; executor.shutdownNow(); scheduledExecutor.shutdownNow(); + sqlTaskExecutionFactory = null; + allOperatorContexts = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/execution/TestPlannerWarnings.java b/core/trino-main/src/test/java/io/trino/execution/TestPlannerWarnings.java index f9631d74e921c..433f7580abb0e 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestPlannerWarnings.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestPlannerWarnings.java @@ -76,6 +76,7 @@ public void setUp() public void tearDown() { queryRunner.close(); + queryRunner = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/execution/TestResetSessionTask.java b/core/trino-main/src/test/java/io/trino/execution/TestResetSessionTask.java index 10180b6ae64b0..de0e9eaa9ef85 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestResetSessionTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestResetSessionTask.java @@ -28,6 +28,7 @@ import io.trino.testing.LocalQueryRunner; import io.trino.transaction.TransactionManager; import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.net.URI; @@ -48,14 +49,16 @@ public class TestResetSessionTask { private static final String CATALOG_NAME = "my_catalog"; private ExecutorService executor = newCachedThreadPool(daemonThreadsNamed(getClass().getSimpleName() + "-%s")); - private final TransactionManager transactionManager; - private final AccessControl accessControl; - private final Metadata metadata; - private final SessionPropertyManager sessionPropertyManager; + private LocalQueryRunner queryRunner; + private TransactionManager transactionManager; + private AccessControl accessControl; + private Metadata metadata; + private SessionPropertyManager sessionPropertyManager; - public TestResetSessionTask() + @BeforeClass + public void setUp() { - LocalQueryRunner queryRunner = LocalQueryRunner.builder(TEST_SESSION) + queryRunner = LocalQueryRunner.builder(TEST_SESSION) .withExtraSystemSessionProperties(ImmutableSet.of(() -> ImmutableList.of( stringProperty( "foo", @@ -86,6 +89,12 @@ public void tearDown() { executor.shutdownNow(); executor = null; + queryRunner.close(); + queryRunner = null; + transactionManager = null; + accessControl = null; + metadata = null; + sessionPropertyManager = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSetPathTask.java b/core/trino-main/src/test/java/io/trino/execution/TestSetPathTask.java index 6005ef5538cf7..e01e4f7f8b89e 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSetPathTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSetPathTask.java @@ -26,6 +26,7 @@ import io.trino.sql.tree.SetPath; import io.trino.transaction.TransactionManager; import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.net.URI; @@ -44,13 +45,14 @@ public class TestSetPathTask { - private final TransactionManager transactionManager; - private final AccessControl accessControl; - private final Metadata metadata; + private TransactionManager transactionManager; + private AccessControl accessControl; + private Metadata metadata; private ExecutorService executor = newCachedThreadPool(daemonThreadsNamed(getClass().getSimpleName() + "-%s")); - public TestSetPathTask() + @BeforeClass + public void setUp() { transactionManager = createTestTransactionManager(); accessControl = new AllowAllAccessControl(); @@ -65,6 +67,9 @@ public void tearDown() { executor.shutdownNow(); executor = null; + transactionManager = null; + accessControl = null; + metadata = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSetSessionTask.java b/core/trino-main/src/test/java/io/trino/execution/TestSetSessionTask.java index c5f2f0a26bdc3..af3b59eeb38d2 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSetSessionTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSetSessionTask.java @@ -35,6 +35,7 @@ import io.trino.testing.LocalQueryRunner; import io.trino.transaction.TransactionManager; import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.net.URI; @@ -69,15 +70,18 @@ private enum Size LARGE, } - private final TransactionManager transactionManager; - private final AccessControl accessControl; - private final Metadata metadata; - private final PlannerContext plannerContext; - private final SessionPropertyManager sessionPropertyManager; + private LocalQueryRunner queryRunner; + private TransactionManager transactionManager; + private AccessControl accessControl; + private Metadata metadata; + private PlannerContext plannerContext; + private SessionPropertyManager sessionPropertyManager; + private ExecutorService executor = newCachedThreadPool(daemonThreadsNamed(getClass().getSimpleName() + "-%s")); - public TestSetSessionTask() + @BeforeClass + public void setUp() { - LocalQueryRunner queryRunner = LocalQueryRunner.builder(TEST_SESSION) + queryRunner = LocalQueryRunner.builder(TEST_SESSION) .withExtraSystemSessionProperties(ImmutableSet.of(() -> ImmutableList.of( stringProperty( "foo", @@ -124,13 +128,18 @@ private static void validatePositive(Object value) } } - private ExecutorService executor = newCachedThreadPool(daemonThreadsNamed(getClass().getSimpleName() + "-%s")); - @AfterClass(alwaysRun = true) public void tearDown() { + queryRunner.close(); + queryRunner = null; executor.shutdownNow(); executor = null; + transactionManager = null; + accessControl = null; + metadata = null; + plannerContext = null; + sessionPropertyManager = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSetTimeZoneTask.java b/core/trino-main/src/test/java/io/trino/execution/TestSetTimeZoneTask.java index 29c0d34c3f6da..19fea002cd7d9 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSetTimeZoneTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSetTimeZoneTask.java @@ -27,6 +27,7 @@ import io.trino.sql.tree.StringLiteral; import io.trino.testing.LocalQueryRunner; import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.net.URI; @@ -50,10 +51,11 @@ public class TestSetTimeZoneTask { - private final LocalQueryRunner localQueryRunner; private ExecutorService executor = newCachedThreadPool(daemonThreadsNamed(getClass().getSimpleName() + "-%s")); + private LocalQueryRunner localQueryRunner; - public TestSetTimeZoneTask() + @BeforeClass + public void setUp() { localQueryRunner = LocalQueryRunner.create(TEST_SESSION); } @@ -63,6 +65,8 @@ public void tearDown() { executor.shutdownNow(); executor = null; + localQueryRunner.close(); + localQueryRunner = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSqlTask.java b/core/trino-main/src/test/java/io/trino/execution/TestSqlTask.java index ff1b052d9d766..913e01deae0df 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSqlTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSqlTask.java @@ -37,6 +37,7 @@ import io.trino.spiller.SpillSpaceTracker; import io.trino.sql.planner.LocalExecutionPlanner; import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.net.URI; @@ -81,14 +82,16 @@ public class TestSqlTask { public static final OutputBufferId OUT = new OutputBufferId(0); - private final TaskExecutor taskExecutor; - private final ScheduledExecutorService taskNotificationExecutor; - private final ScheduledExecutorService driverYieldExecutor; - private final SqlTaskExecutionFactory sqlTaskExecutionFactory; + + private TaskExecutor taskExecutor; + private ScheduledExecutorService taskNotificationExecutor; + private ScheduledExecutorService driverYieldExecutor; + private SqlTaskExecutionFactory sqlTaskExecutionFactory; private final AtomicInteger nextTaskId = new AtomicInteger(); - public TestSqlTask() + @BeforeClass + public void setUp() { taskExecutor = new TaskExecutor(8, 16, 3, 4, Ticker.systemTicker()); taskExecutor.start(); @@ -110,8 +113,10 @@ public TestSqlTask() public void destroy() { taskExecutor.stop(); + taskExecutor = null; taskNotificationExecutor.shutdownNow(); driverYieldExecutor.shutdown(); + sqlTaskExecutionFactory = null; } @Test(timeOut = 30_000) diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskExecution.java b/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskExecution.java index 73a32375f0f09..b04fafbeea8df 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskExecution.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskExecution.java @@ -103,8 +103,8 @@ public void testSimple() ScheduledExecutorService taskNotificationExecutor = newScheduledThreadPool(10, threadsNamed("task-notification-%s")); ScheduledExecutorService driverYieldExecutor = newScheduledThreadPool(2, threadsNamed("driver-yield-%s")); TaskExecutor taskExecutor = new TaskExecutor(5, 10, 3, 4, Ticker.systemTicker()); - taskExecutor.start(); + taskExecutor.start(); try { TaskStateMachine taskStateMachine = new TaskStateMachine(TASK_ID, taskNotificationExecutor); PartitionedOutputBuffer outputBuffer = newTestingOutputBuffer(taskNotificationExecutor); diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskManager.java b/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskManager.java index cfeb71077d5b9..afaaa45bb5b52 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskManager.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskManager.java @@ -52,6 +52,7 @@ import io.trino.spiller.NodeSpillConfig; import io.trino.version.EmbedVersion; import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.annotation.concurrent.GuardedBy; @@ -90,12 +91,13 @@ public class TestSqlTaskManager private static final TaskId TASK_ID = new TaskId(new StageId("query", 0), 1, 0); public static final OutputBufferId OUT = new OutputBufferId(0); - private final TaskExecutor taskExecutor; - private final TaskManagementExecutor taskManagementExecutor; - private final LocalMemoryManager localMemoryManager; - private final LocalSpillManager localSpillManager; + private TaskExecutor taskExecutor; + private TaskManagementExecutor taskManagementExecutor; + private LocalMemoryManager localMemoryManager; + private LocalSpillManager localSpillManager; - public TestSqlTaskManager() + @BeforeClass + public void setUp() { localMemoryManager = new LocalMemoryManager(new NodeMemoryConfig()); localSpillManager = new LocalSpillManager(new NodeSpillConfig()); @@ -108,7 +110,9 @@ public TestSqlTaskManager() public void tearDown() { taskExecutor.stop(); + taskExecutor = null; taskManagementExecutor.close(); + taskManagementExecutor = null; } @Test @@ -272,30 +276,32 @@ public void testFailStuckSplitTasks() TaskExecutor taskExecutor = new TaskExecutor(4, 8, 3, 4, ticker); // Here we explicitly enqueue an indefinite running split runner taskExecutor.enqueueSplits(taskHandle, false, ImmutableList.of(mockSplitRunner)); - taskExecutor.start(); - - // wait for the task executor to start processing the split - mockSplitRunner.waitForStart(); - - TaskManagerConfig taskManagerConfig = new TaskManagerConfig() - .setInterruptStuckSplitTasksEnabled(true) - .setInterruptStuckSplitTasksDetectionInterval(new Duration(10, SECONDS)) - .setInterruptStuckSplitTasksWarningThreshold(new Duration(10, SECONDS)) - .setInterruptStuckSplitTasksTimeout(new Duration(10, SECONDS)); - - try (SqlTaskManager sqlTaskManager = createSqlTaskManager(taskManagerConfig, new NodeMemoryConfig(), taskExecutor, stackTraceElements -> true)) { - sqlTaskManager.addStateChangeListener(TASK_ID, (state) -> { - if (state.isDone()) { - taskExecutor.removeTask(taskHandle); - } - }); - - ticker.increment(30, SECONDS); - sqlTaskManager.failStuckSplitTasks(); - mockSplitRunner.waitForFinish(); - assertEquals(sqlTaskManager.getAllTaskInfo().size(), 1); - assertEquals(sqlTaskManager.getAllTaskInfo().get(0).getTaskStatus().getState(), TaskState.FAILED); + taskExecutor.start(); + try { + // wait for the task executor to start processing the split + mockSplitRunner.waitForStart(); + + TaskManagerConfig taskManagerConfig = new TaskManagerConfig() + .setInterruptStuckSplitTasksEnabled(true) + .setInterruptStuckSplitTasksDetectionInterval(new Duration(10, SECONDS)) + .setInterruptStuckSplitTasksWarningThreshold(new Duration(10, SECONDS)) + .setInterruptStuckSplitTasksTimeout(new Duration(10, SECONDS)); + + try (SqlTaskManager sqlTaskManager = createSqlTaskManager(taskManagerConfig, new NodeMemoryConfig(), taskExecutor, stackTraceElements -> true)) { + sqlTaskManager.addStateChangeListener(TASK_ID, (state) -> { + if (state.isDone()) { + taskExecutor.removeTask(taskHandle); + } + }); + + ticker.increment(30, SECONDS); + sqlTaskManager.failStuckSplitTasks(); + + mockSplitRunner.waitForFinish(); + assertEquals(sqlTaskManager.getAllTaskInfo().size(), 1); + assertEquals(sqlTaskManager.getAllTaskInfo().get(0).getTaskStatus().getState(), TaskState.FAILED); + } } finally { taskExecutor.stop(); diff --git a/core/trino-main/src/test/java/io/trino/execution/executor/TestTaskExecutor.java b/core/trino-main/src/test/java/io/trino/execution/executor/TestTaskExecutor.java index 93fefba26d33c..888d30c0231ad 100644 --- a/core/trino-main/src/test/java/io/trino/execution/executor/TestTaskExecutor.java +++ b/core/trino-main/src/test/java/io/trino/execution/executor/TestTaskExecutor.java @@ -58,10 +58,10 @@ public void testTasksComplete() Duration splitProcessingDurationThreshold = new Duration(10, MINUTES); TaskExecutor taskExecutor = new TaskExecutor(4, 8, 3, 4, ticker); - taskExecutor.start(); - ticker.increment(20, MILLISECONDS); + taskExecutor.start(); try { + ticker.increment(20, MILLISECONDS); TaskId taskId = new TaskId(new StageId("test", 0), 0, 0); TaskHandle taskHandle = taskExecutor.addTask(taskId, () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); @@ -156,10 +156,10 @@ public void testQuantaFairness() { TestingTicker ticker = new TestingTicker(); TaskExecutor taskExecutor = new TaskExecutor(1, 2, 3, 4, ticker); - taskExecutor.start(); - ticker.increment(20, MILLISECONDS); + taskExecutor.start(); try { + ticker.increment(20, MILLISECONDS); TaskHandle shortQuantaTaskHandle = taskExecutor.addTask(new TaskId(new StageId("short_quanta", 0), 0, 0), () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); TaskHandle longQuantaTaskHandle = taskExecutor.addTask(new TaskId(new StageId("long_quanta", 0), 0, 0), () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); @@ -190,10 +190,10 @@ public void testLevelMovement() { TestingTicker ticker = new TestingTicker(); TaskExecutor taskExecutor = new TaskExecutor(2, 2, 3, 4, ticker); - taskExecutor.start(); - ticker.increment(20, MILLISECONDS); + taskExecutor.start(); try { + ticker.increment(20, MILLISECONDS); TaskHandle testTaskHandle = taskExecutor.addTask(new TaskId(new StageId("test", 0), 0, 0), () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); Phaser globalPhaser = new Phaser(); @@ -229,10 +229,10 @@ public void testLevelMultipliers() { TestingTicker ticker = new TestingTicker(); TaskExecutor taskExecutor = new TaskExecutor(6, 3, 3, 4, new MultilevelSplitQueue(2), ticker); - taskExecutor.start(); - ticker.increment(20, MILLISECONDS); + taskExecutor.start(); try { + ticker.increment(20, MILLISECONDS); for (int i = 0; i < (LEVEL_THRESHOLD_SECONDS.length - 1); i++) { TaskHandle[] taskHandles = { taskExecutor.addTask(new TaskId(new StageId("test1", 0), 0, 0), () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()), @@ -307,8 +307,8 @@ public void testTaskHandle() { TestingTicker ticker = new TestingTicker(); TaskExecutor taskExecutor = new TaskExecutor(4, 8, 3, 4, ticker); - taskExecutor.start(); + taskExecutor.start(); try { TaskId taskId = new TaskId(new StageId("test", 0), 0, 0); TaskHandle taskHandle = taskExecutor.addTask(taskId, () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); @@ -382,6 +382,7 @@ public void testMinMaxDriversPerTask() MultilevelSplitQueue splitQueue = new MultilevelSplitQueue(2); TestingTicker ticker = new TestingTicker(); TaskExecutor taskExecutor = new TaskExecutor(4, 16, 1, maxDriversPerTask, splitQueue, ticker); + taskExecutor.start(); try { TaskHandle testTaskHandle = taskExecutor.addTask(new TaskId(new StageId("test", 0), 0, 0), () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); @@ -422,6 +423,7 @@ public void testUserSpecifiedMaxDriversPerTask() TestingTicker ticker = new TestingTicker(); // create a task executor with min/max drivers per task to be 2 and 4 TaskExecutor taskExecutor = new TaskExecutor(4, 16, 2, 4, splitQueue, ticker); + taskExecutor.start(); try { // overwrite the max drivers per task to be 1 @@ -461,8 +463,8 @@ public void testMinDriversPerTaskWhenTargetConcurrencyIncreases() TestingTicker ticker = new TestingTicker(); // create a task executor with min/max drivers per task to be 2 TaskExecutor taskExecutor = new TaskExecutor(4, 1, 2, 2, splitQueue, ticker); - taskExecutor.start(); + taskExecutor.start(); try { TaskHandle testTaskHandle = taskExecutor.addTask( new TaskId(new StageId(new QueryId("test"), 0), 0, 0), diff --git a/core/trino-main/src/test/java/io/trino/metadata/TestDiscoveryNodeManager.java b/core/trino-main/src/test/java/io/trino/metadata/TestDiscoveryNodeManager.java index d161620bfabd0..5a29fa90b86dc 100644 --- a/core/trino-main/src/test/java/io/trino/metadata/TestDiscoveryNodeManager.java +++ b/core/trino-main/src/test/java/io/trino/metadata/TestDiscoveryNodeManager.java @@ -30,6 +30,7 @@ import io.trino.connector.system.GlobalSystemConnector; import io.trino.failuredetector.NoOpFailureDetector; import io.trino.server.InternalCommunicationConfig; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -87,6 +88,13 @@ public void setup() selector.announceNodes(activeNodes, inactiveNodes); } + @AfterMethod(alwaysRun = true) + public void tearDown() + { + testHttpClient.close(); + testHttpClient = null; + } + @Test public void testGetAllNodes() { diff --git a/core/trino-main/src/test/java/io/trino/server/TestGenerateTokenFilter.java b/core/trino-main/src/test/java/io/trino/server/TestGenerateTokenFilter.java index c9715616675bc..6ecf788fb8c1d 100644 --- a/core/trino-main/src/test/java/io/trino/server/TestGenerateTokenFilter.java +++ b/core/trino-main/src/test/java/io/trino/server/TestGenerateTokenFilter.java @@ -76,6 +76,8 @@ public void tearDown() throws Exception { closeAll(server, httpClient); + server = null; + httpClient = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/server/TestNodeResource.java b/core/trino-main/src/test/java/io/trino/server/TestNodeResource.java index f26854b631fbd..765990ed1afa5 100644 --- a/core/trino-main/src/test/java/io/trino/server/TestNodeResource.java +++ b/core/trino-main/src/test/java/io/trino/server/TestNodeResource.java @@ -47,6 +47,8 @@ public void tearDown() throws Exception { closeAll(server, client); + server = null; + client = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/server/TestQueryResource.java b/core/trino-main/src/test/java/io/trino/server/TestQueryResource.java index 9e0ffd0d58b85..a4ed8ad99b7d7 100644 --- a/core/trino-main/src/test/java/io/trino/server/TestQueryResource.java +++ b/core/trino-main/src/test/java/io/trino/server/TestQueryResource.java @@ -82,6 +82,8 @@ public void teardown() throws Exception { closeAll(server, client); + server = null; + client = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/server/TestQueryStateInfoResource.java b/core/trino-main/src/test/java/io/trino/server/TestQueryStateInfoResource.java index bd39e31694537..2376be6cdf9eb 100644 --- a/core/trino-main/src/test/java/io/trino/server/TestQueryStateInfoResource.java +++ b/core/trino-main/src/test/java/io/trino/server/TestQueryStateInfoResource.java @@ -119,6 +119,8 @@ public void tearDown() closer.register(server); closer.register(client); closer.close(); + server = null; + client = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/server/security/oauth2/BaseOAuth2WebUiAuthenticationFilterTest.java b/core/trino-main/src/test/java/io/trino/server/security/oauth2/BaseOAuth2WebUiAuthenticationFilterTest.java index e8f39b46c4b39..f8a2ea2078546 100644 --- a/core/trino-main/src/test/java/io/trino/server/security/oauth2/BaseOAuth2WebUiAuthenticationFilterTest.java +++ b/core/trino-main/src/test/java/io/trino/server/security/oauth2/BaseOAuth2WebUiAuthenticationFilterTest.java @@ -18,7 +18,6 @@ import com.google.inject.Key; import io.airlift.log.Level; import io.airlift.log.Logging; -import io.airlift.testing.Closeables; import io.jsonwebtoken.impl.DefaultClaims; import io.trino.server.testing.TestingTrinoServer; import io.trino.server.ui.OAuth2WebUiAuthenticationFilter; @@ -49,6 +48,7 @@ import java.util.Optional; import java.util.UUID; +import static io.airlift.testing.Closeables.closeAll; import static io.trino.client.OkHttpUtil.setupInsecureSsl; import static io.trino.server.security.jwt.JwtUtil.newJwtBuilder; import static io.trino.server.security.oauth2.TokenEndpointAuthMethod.CLIENT_SECRET_BASIC; @@ -142,7 +142,9 @@ public void tearDown() { logging.clearLevel(OAuth2WebUiAuthenticationFilter.class.getName()); logging.clearLevel(OAuth2Service.class.getName()); - Closeables.closeAll(server, hydraIdP); + closeAll(server, hydraIdP); + server = null; + hydraIdP = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/spiller/TestFileSingleStreamSpillerFactory.java b/core/trino-main/src/test/java/io/trino/spiller/TestFileSingleStreamSpillerFactory.java index 1299efefd8d95..f45c9557e1011 100644 --- a/core/trino-main/src/test/java/io/trino/spiller/TestFileSingleStreamSpillerFactory.java +++ b/core/trino-main/src/test/java/io/trino/spiller/TestFileSingleStreamSpillerFactory.java @@ -76,6 +76,7 @@ public void tearDown() throws Exception { closer.close(); + closer = null; } @Test diff --git a/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java b/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java index d3a1c4d632d60..40e0b1725512b 100644 --- a/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java +++ b/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java @@ -224,7 +224,7 @@ public class TestAnalyzer private static final SqlParser SQL_PARSER = new SqlParser(); - private final Closer closer = Closer.create(); + private Closer closer; private TransactionManager transactionManager; private AccessControl accessControl; private PlannerContext plannerContext; @@ -6625,6 +6625,7 @@ public void testTableFunctionAliasing() @BeforeClass public void setup() { + closer = Closer.create(); LocalQueryRunner queryRunner = LocalQueryRunner.create(TEST_SESSION); closer.register(queryRunner); transactionManager = queryRunner.getTransactionManager(); @@ -6959,6 +6960,12 @@ public void tearDown() throws Exception { closer.close(); + closer = null; + transactionManager = null; + accessControl = null; + plannerContext = null; + tablePropertyManager = null; + analyzePropertyManager = null; } private void inSetupTransaction(Consumer consumer) diff --git a/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestAnonymizeJsonRepresentation.java b/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestAnonymizeJsonRepresentation.java index 0ade639f8f456..f7bf354e993e4 100644 --- a/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestAnonymizeJsonRepresentation.java +++ b/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestAnonymizeJsonRepresentation.java @@ -34,6 +34,7 @@ import io.trino.sql.planner.plan.JoinNode; import io.trino.sql.planner.plan.PlanNode; import io.trino.testing.LocalQueryRunner; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -85,6 +86,13 @@ public void setUp() queryRunner.createCatalog(TEST_SESSION.getCatalog().get(), new TpchConnectorFactory(1), ImmutableMap.of()); } + @AfterClass(alwaysRun = true) + public void tearDown() + { + queryRunner.close(); + queryRunner = null; + } + @Test public void testAggregationPlan() { diff --git a/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestJsonRepresentation.java b/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestJsonRepresentation.java index 2de5cbef33601..8515ecec3301f 100644 --- a/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestJsonRepresentation.java +++ b/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestJsonRepresentation.java @@ -30,6 +30,7 @@ import io.trino.sql.planner.plan.PlanNode; import io.trino.testing.LocalQueryRunner; import io.trino.testing.MaterializedResult; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -73,6 +74,13 @@ public void setUp() queryRunner.createCatalog(TEST_SESSION.getCatalog().get(), new TpchConnectorFactory(1), ImmutableMap.of()); } + @AfterClass(alwaysRun = true) + public void tearDown() + { + queryRunner.close(); + queryRunner = null; + } + @Test public void testDistributedJsonPlan() { diff --git a/core/trino-main/src/test/java/io/trino/sql/planner/sanity/TestValidateScaledWritersUsage.java b/core/trino-main/src/test/java/io/trino/sql/planner/sanity/TestValidateScaledWritersUsage.java index 31e1c3f72a2ae..7621ae107d53d 100644 --- a/core/trino-main/src/test/java/io/trino/sql/planner/sanity/TestValidateScaledWritersUsage.java +++ b/core/trino-main/src/test/java/io/trino/sql/planner/sanity/TestValidateScaledWritersUsage.java @@ -37,6 +37,7 @@ import io.trino.sql.planner.plan.TableScanNode; import io.trino.testing.LocalQueryRunner; import io.trino.testing.TestingTransactionHandle; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -55,13 +56,13 @@ public class TestValidateScaledWritersUsage extends BasePlanTest { + private LocalQueryRunner queryRunner; private PlannerContext plannerContext; private PlanBuilder planBuilder; private Symbol symbol; private TableScanNode tableScanNode; private CatalogHandle catalogSupportingScaledWriters; private CatalogHandle catalogNotSupportingScaledWriters; - private LocalQueryRunner queryRunner; private SchemaTableName schemaTableName; @BeforeClass @@ -84,6 +85,18 @@ public void setup() tableScanNode = planBuilder.tableScan(nationTableHandle, ImmutableList.of(symbol), ImmutableMap.of(symbol, nationkeyColumnHandle)); } + @AfterClass(alwaysRun = true) + public void tearDown() + { + queryRunner.close(); + queryRunner = null; + plannerContext = null; + planBuilder = null; + tableScanNode = null; + catalogSupportingScaledWriters = null; + catalogNotSupportingScaledWriters = null; + } + private MockConnectorFactory createConnectorFactorySupportingReportingBytesWritten(boolean supportsWrittenBytes, String name) { return MockConnectorFactory.builder() diff --git a/core/trino-main/src/test/java/io/trino/sql/query/TestColumnMask.java b/core/trino-main/src/test/java/io/trino/sql/query/TestColumnMask.java index 0754dddf1ca15..9b7078b05f7fc 100644 --- a/core/trino-main/src/test/java/io/trino/sql/query/TestColumnMask.java +++ b/core/trino-main/src/test/java/io/trino/sql/query/TestColumnMask.java @@ -158,6 +158,7 @@ public void init() @AfterAll public void teardown() { + accessControl = null; assertions.close(); assertions = null; } diff --git a/core/trino-main/src/test/java/io/trino/sql/query/TestRowFilter.java b/core/trino-main/src/test/java/io/trino/sql/query/TestRowFilter.java index fc0d05527dd2f..6b10555248b01 100644 --- a/core/trino-main/src/test/java/io/trino/sql/query/TestRowFilter.java +++ b/core/trino-main/src/test/java/io/trino/sql/query/TestRowFilter.java @@ -144,6 +144,7 @@ public void init() @AfterAll public void teardown() { + accessControl = null; assertions.close(); assertions = null; } diff --git a/lib/trino-orc/src/test/java/io/trino/orc/TestCachingOrcDataSource.java b/lib/trino-orc/src/test/java/io/trino/orc/TestCachingOrcDataSource.java index da5b015580901..05b6d995b2970 100644 --- a/lib/trino-orc/src/test/java/io/trino/orc/TestCachingOrcDataSource.java +++ b/lib/trino-orc/src/test/java/io/trino/orc/TestCachingOrcDataSource.java @@ -90,6 +90,7 @@ public void tearDown() throws Exception { tempFile.close(); + tempFile = null; } @Test diff --git a/lib/trino-orc/src/test/java/io/trino/orc/TestStructColumnReader.java b/lib/trino-orc/src/test/java/io/trino/orc/TestStructColumnReader.java index edff0437772c0..15f2f2c0384ec 100644 --- a/lib/trino-orc/src/test/java/io/trino/orc/TestStructColumnReader.java +++ b/lib/trino-orc/src/test/java/io/trino/orc/TestStructColumnReader.java @@ -75,6 +75,7 @@ public void tearDown() throws IOException { tempFile.close(); + tempFile = null; } /** diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/BaseJdbcConnectionCreationTest.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/BaseJdbcConnectionCreationTest.java index 2601de72853a7..cf022fb35d23c 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/BaseJdbcConnectionCreationTest.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/BaseJdbcConnectionCreationTest.java @@ -16,6 +16,7 @@ import io.trino.spi.connector.ConnectorSession; import io.trino.testing.AbstractTestQueryFramework; import org.intellij.lang.annotations.Language; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -45,6 +46,14 @@ public void verifySetup() connectionFactory.assertThatNoConnectionHasLeaked(); } + @AfterClass(alwaysRun = true) + public void destroy() + throws Exception + { + connectionFactory.close(); + connectionFactory = null; + } + protected void assertJdbcConnections(@Language("SQL") String query, int expectedJdbcConnectionsCount, Optional errorMessage) { int before = connectionFactory.openConnections.get(); diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestCachingJdbcClient.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestCachingJdbcClient.java index a280a4d2229cd..0994f797f383d 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestCachingJdbcClient.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestCachingJdbcClient.java @@ -127,7 +127,9 @@ public void tearDown() throws Exception { executor.shutdownNow(); + executor = null; database.close(); + database = null; } @Test diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java index 3388c3a253a2d..6fc2296924e3d 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java @@ -112,6 +112,7 @@ public void tearDown() throws Exception { database.close(); + database = null; } @Test diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcQueryBuilder.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcQueryBuilder.java index a47773d9903bd..7379a2e4a619b 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcQueryBuilder.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcQueryBuilder.java @@ -181,6 +181,7 @@ public void teardown() throws Exception { database.close(); + database = null; } @Test diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcClient.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcClient.java index 2ddbf423559ad..8d37fba442d05 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcClient.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcClient.java @@ -66,6 +66,7 @@ public void tearDown() throws Exception { database.close(); + database = null; } @Test diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcRecordSet.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcRecordSet.java index 6988983d54911..365c70ba591b4 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcRecordSet.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcRecordSet.java @@ -67,6 +67,8 @@ public void tearDown() closeAll( database, () -> executor.shutdownNow()); + database = null; + executor = null; } @Test diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcRecordSetProvider.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcRecordSetProvider.java index cc5f31a25d67a..a52a1b0ef818c 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcRecordSetProvider.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcRecordSetProvider.java @@ -90,6 +90,8 @@ public void tearDown() closeAll( database, () -> executor.shutdownNow()); + database = null; + executor = null; } @Test diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/CassandraServer.java b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/CassandraServer.java index 1bc5d70d87e3d..3011bbca208d1 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/CassandraServer.java +++ b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/CassandraServer.java @@ -25,6 +25,7 @@ import io.airlift.json.JsonCodec; import io.airlift.log.Logger; import io.airlift.units.Duration; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.GenericContainer; import java.io.Closeable; @@ -196,9 +197,13 @@ private void refreshSizeEstimates() @Override public void close() { - if (session != null) { - session.close(); - } + session.close(); dockerContainer.close(); } + + @ResourcePresence + public boolean isRunning() + { + return dockerContainer.getContainerId() != null; + } } diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnectorTest.java b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnectorTest.java index 3c118917d772a..64b67418e3e38 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnectorTest.java +++ b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnectorTest.java @@ -27,6 +27,7 @@ import io.trino.testing.assertions.Assert; import io.trino.testing.sql.TestTable; import org.testng.SkipException; +import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import java.math.BigDecimal; @@ -135,6 +136,13 @@ protected QueryRunner createQueryRunner() return createCassandraQueryRunner(server, ImmutableMap.of(), ImmutableMap.of(), REQUIRED_TPCH_TABLES); } + @AfterClass(alwaysRun = true) + public void cleanUp() + { + session.close(); + session = null; + } + @Override protected TestTable createTableWithDefaultColumns() { diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraTokenSplitManager.java b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraTokenSplitManager.java index 598b8d00ff898..3ebc230fbc786 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraTokenSplitManager.java +++ b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraTokenSplitManager.java @@ -50,6 +50,9 @@ public void setUp() public void tearDown() { server.close(); + server = null; + session.close(); + session = null; } @Test diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraTypeMapping.java b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraTypeMapping.java index 0c3fbee287112..65faa0257d357 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraTypeMapping.java +++ b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraTypeMapping.java @@ -28,6 +28,7 @@ import io.trino.testing.datatype.SqlDataTypeTest; import io.trino.testing.sql.TrinoSqlExecutor; import org.intellij.lang.annotations.Language; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -144,6 +145,13 @@ protected QueryRunner createQueryRunner() ImmutableList.of()); } + @AfterClass(alwaysRun = true) + public void cleanUp() + { + session.close(); + session = null; + } + @Test public void testBoolean() { diff --git a/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/TestingClickHouseServer.java b/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/TestingClickHouseServer.java index 55bcf7cc52048..0e88ee3cc4972 100644 --- a/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/TestingClickHouseServer.java +++ b/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/TestingClickHouseServer.java @@ -14,6 +14,7 @@ package io.trino.plugin.clickhouse; import com.clickhouse.client.ClickHouseVersion; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.ClickHouseContainer; import org.testcontainers.utility.DockerImageName; @@ -102,4 +103,10 @@ public void close() { dockerContainer.stop(); } + + @ResourcePresence + public boolean isRunning() + { + return dockerContainer.getContainerId() != null; + } } diff --git a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/BaseDeltaLakeConnectorSmokeTest.java b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/BaseDeltaLakeConnectorSmokeTest.java index 2638e7964ab2c..2a43c3ed842da 100644 --- a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/BaseDeltaLakeConnectorSmokeTest.java +++ b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/BaseDeltaLakeConnectorSmokeTest.java @@ -119,6 +119,8 @@ public abstract class BaseDeltaLakeConnectorSmokeTest protected HiveMinioDataLake hiveMinioDataLake; private HiveMetastore metastore; + protected void environmentSetup() {} + protected abstract HiveMinioDataLake createHiveMinioDataLake() throws Exception; @@ -137,6 +139,8 @@ protected abstract QueryRunner createDeltaLakeQueryRunner(Map co protected QueryRunner createQueryRunner() throws Exception { + environmentSetup(); + this.hiveMinioDataLake = closeAfterClass(createHiveMinioDataLake()); this.metastore = new BridgingHiveMetastore( testingThriftHiveMetastoreBuilder() diff --git a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/TestDeltaLakeGcsConnectorSmokeTest.java b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/TestDeltaLakeGcsConnectorSmokeTest.java index 04ca516f3885e..626c9314b9906 100644 --- a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/TestDeltaLakeGcsConnectorSmokeTest.java +++ b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/TestDeltaLakeGcsConnectorSmokeTest.java @@ -71,15 +71,21 @@ public class TestDeltaLakeGcsConnectorSmokeTest private static final FileAttribute READ_ONLY_PERMISSIONS = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-r--r--")); private final String gcpStorageBucket; - private final Path gcpCredentialsFile; - private final FileSystem fileSystem; + private final String gcpCredentialKey; + + private Path gcpCredentialsFile; + private FileSystem fileSystem; @Parameters({"testing.gcp-storage-bucket", "testing.gcp-credentials-key"}) public TestDeltaLakeGcsConnectorSmokeTest(String gcpStorageBucket, String gcpCredentialKey) { this.gcpStorageBucket = requireNonNull(gcpStorageBucket, "gcpStorageBucket is null"); + this.gcpCredentialKey = requireNonNull(gcpCredentialKey, "gcpCredentialKey is null"); + } - requireNonNull(gcpCredentialKey, "gcpCredentialKey is null"); + @Override + protected void environmentSetup() + { InputStream jsonKey = new ByteArrayInputStream(Base64.getDecoder().decode(gcpCredentialKey)); try { this.gcpCredentialsFile = Files.createTempFile("gcp-credentials", ".json", READ_ONLY_PERMISSIONS); @@ -111,6 +117,7 @@ public void removeTestData() // The GCS bucket should be configured to expire objects automatically. Clean up issues do not need to fail the test. LOG.warn(e, "Failed to clean up GCS test directory: %s", bucketUrl()); } + fileSystem = null; } } diff --git a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/metastore/glue/TestDeltaLakeRenameToWithGlueMetastore.java b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/metastore/glue/TestDeltaLakeRenameToWithGlueMetastore.java index 092510f191eee..cc84e1471c5e4 100644 --- a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/metastore/glue/TestDeltaLakeRenameToWithGlueMetastore.java +++ b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/metastore/glue/TestDeltaLakeRenameToWithGlueMetastore.java @@ -98,7 +98,7 @@ public void testRenameOfManagedTable() } } - @AfterClass + @AfterClass(alwaysRun = true) public void cleanup() { assertUpdate("DROP SCHEMA IF EXISTS " + SCHEMA); diff --git a/plugin/trino-druid/src/test/java/io/trino/plugin/druid/BaseDruidConnectorTest.java b/plugin/trino-druid/src/test/java/io/trino/plugin/druid/BaseDruidConnectorTest.java index 556de51074301..93e8b4dc8a147 100644 --- a/plugin/trino-druid/src/test/java/io/trino/plugin/druid/BaseDruidConnectorTest.java +++ b/plugin/trino-druid/src/test/java/io/trino/plugin/druid/BaseDruidConnectorTest.java @@ -57,6 +57,7 @@ public void destroy() { if (druidServer != null) { druidServer.close(); + druidServer = null; } } diff --git a/plugin/trino-druid/src/test/java/io/trino/plugin/druid/TestDruidTypeMapping.java b/plugin/trino-druid/src/test/java/io/trino/plugin/druid/TestDruidTypeMapping.java index a8a00ab67282d..a2801ffacc5e0 100644 --- a/plugin/trino-druid/src/test/java/io/trino/plugin/druid/TestDruidTypeMapping.java +++ b/plugin/trino-druid/src/test/java/io/trino/plugin/druid/TestDruidTypeMapping.java @@ -19,6 +19,7 @@ import io.trino.testing.QueryRunner; import io.trino.testing.datatype.DataSetup; import io.trino.testing.datatype.SqlDataTypeTest; +import org.testng.annotations.AfterClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -43,6 +44,13 @@ protected QueryRunner createQueryRunner() return DruidQueryRunner.createDruidQueryRunnerTpch(druidServer, ImmutableMap.of(), ImmutableList.of()); } + @AfterClass(alwaysRun = true) + public void tearDown() + { + druidServer.close(); + druidServer = null; + } + @Test public void testLong() { diff --git a/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/BaseElasticsearchConnectorTest.java b/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/BaseElasticsearchConnectorTest.java index b2088b2e62a43..23619fb5d19c8 100644 --- a/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/BaseElasticsearchConnectorTest.java +++ b/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/BaseElasticsearchConnectorTest.java @@ -87,6 +87,16 @@ protected QueryRunner createQueryRunner() catalogName); } + @AfterClass(alwaysRun = true) + public final void destroy() + throws IOException + { + elasticsearch.stop(); + elasticsearch = null; + client.close(); + client = null; + } + @SuppressWarnings("DuplicateBranchesInSwitch") @Override protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) @@ -140,14 +150,6 @@ protected Object[][] largeInValuesCountData() }; } - @AfterClass(alwaysRun = true) - public final void destroy() - throws IOException - { - elasticsearch.stop(); - client.close(); - } - @Test public void testWithoutBackpressure() { diff --git a/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/ElasticsearchServer.java b/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/ElasticsearchServer.java index 0ae65a4211568..8f3da20229d14 100644 --- a/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/ElasticsearchServer.java +++ b/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/ElasticsearchServer.java @@ -14,6 +14,7 @@ package io.trino.plugin.elasticsearch; import com.google.common.net.HostAndPort; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.Network; import org.testcontainers.elasticsearch.ElasticsearchContainer; import org.testcontainers.utility.DockerImageName; @@ -71,6 +72,12 @@ public void stop() deleteRecursively(configurationPath, ALLOW_INSECURE); } + @ResourcePresence + public boolean isRunning() + { + return container.getContainerId() != null; + } + public HostAndPort getAddress() { return HostAndPort.fromString(container.getHttpHostAddress()); diff --git a/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/TestDisabledLegacyPassThroughQuery.java b/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/TestDisabledLegacyPassThroughQuery.java index 2a790f653ed98..73388e36ca18d 100644 --- a/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/TestDisabledLegacyPassThroughQuery.java +++ b/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/TestDisabledLegacyPassThroughQuery.java @@ -54,6 +54,7 @@ public final void destroy() throws IOException { elasticsearch.stop(); + elasticsearch = null; } @Test diff --git a/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/TestElasticsearchBackpressure.java b/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/TestElasticsearchBackpressure.java index ac2304fa44d71..b869ad0c23792 100644 --- a/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/TestElasticsearchBackpressure.java +++ b/plugin/trino-elasticsearch/src/test/java/io/trino/plugin/elasticsearch/TestElasticsearchBackpressure.java @@ -60,8 +60,11 @@ public final void destroy() throws IOException { elasticsearchNginxProxy.stop(); + elasticsearchNginxProxy = null; elasticsearch.stop(); + elasticsearch = null; network.close(); + network = null; } @Test diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/containers/HiveMinioDataLake.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/containers/HiveMinioDataLake.java index 89102b66129c9..4b6dbcf530fa9 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/containers/HiveMinioDataLake.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/containers/HiveMinioDataLake.java @@ -14,6 +14,7 @@ package io.trino.plugin.hive.containers; import com.google.common.collect.ImmutableMap; +import io.trino.testing.ResourcePresence; import io.trino.testing.containers.Minio; import io.trino.testing.minio.MinioClient; import io.trino.util.AutoCloseableCloser; @@ -99,6 +100,12 @@ public void stop() state = State.STOPPED; } + @ResourcePresence + public boolean isNotStopped() + { + return state != State.STOPPED; + } + public MinioClient getMinioClient() { checkState(state == State.STARTED, "Can't provide client when MinIO state is: %s", state); diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/thrift/MockThriftMetastoreClient.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/thrift/MockThriftMetastoreClient.java index ec7804454f542..70c99277bd69e 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/thrift/MockThriftMetastoreClient.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/thrift/MockThriftMetastoreClient.java @@ -17,6 +17,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import io.trino.plugin.hive.acid.AcidOperation; +import io.trino.testng.services.ManageTestResources; import org.apache.hadoop.hive.metastore.TableType; import org.apache.hadoop.hive.metastore.Warehouse; import org.apache.hadoop.hive.metastore.api.ColumnStatisticsData; @@ -50,6 +51,7 @@ import static org.apache.hadoop.hive.metastore.api.PrincipalType.ROLE; import static org.apache.hadoop.hive.metastore.api.PrincipalType.USER; +@ManageTestResources.Suppress(because = "close() is no-op and instance's resources are negligible") public class MockThriftMetastoreClient implements ThriftMetastoreClient { diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/rubix/TestRubixCaching.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/rubix/TestRubixCaching.java index 4e0e1778df68a..4c88d31395195 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/rubix/TestRubixCaching.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/rubix/TestRubixCaching.java @@ -101,8 +101,8 @@ public class TestRubixCaching { private static final DataSize SMALL_FILE_SIZE = DataSize.of(1, MEGABYTE); private static final DataSize LARGE_FILE_SIZE = DataSize.of(100, MEGABYTE); - private static final MBeanServer BEAN_SERVER = ManagementFactory.getPlatformMBeanServer(); + private MBeanServer mBeanServer; private java.nio.file.Path tempDirectory; private Path cacheStoragePath; private HdfsConfig config; @@ -116,6 +116,8 @@ public class TestRubixCaching public void setup() throws IOException { + mBeanServer = ManagementFactory.getPlatformMBeanServer(); + cacheStoragePath = getStoragePath("/"); config = new HdfsConfig(); List> hiveSessionProperties = getHiveSessionProperties( @@ -237,6 +239,8 @@ public void tearDown() throws IOException { closeFileSystem(nonCachingFileSystem); + nonCachingFileSystem = null; + mBeanServer = null; } @AfterMethod(alwaysRun = true) @@ -557,8 +561,8 @@ private Path getStoragePath(String path) private long getRemoteReadsCount() { try { - long directRemoteReads = (long) BEAN_SERVER.getAttribute(new ObjectName("rubix:name=stats,type=detailed,catalog=catalog"), "Direct_rrc_requests"); - long remoteReads = (long) BEAN_SERVER.getAttribute(new ObjectName("rubix:name=stats,type=detailed,catalog=catalog"), "Remote_rrc_requests"); + long directRemoteReads = (long) mBeanServer.getAttribute(new ObjectName("rubix:name=stats,type=detailed,catalog=catalog"), "Direct_rrc_requests"); + long remoteReads = (long) mBeanServer.getAttribute(new ObjectName("rubix:name=stats,type=detailed,catalog=catalog"), "Remote_rrc_requests"); return directRemoteReads + remoteReads; } catch (Exception exception) { @@ -569,7 +573,7 @@ private long getRemoteReadsCount() private long getCachedReadsCount() { try { - return (long) BEAN_SERVER.getAttribute(new ObjectName("rubix:name=stats,type=detailed,catalog=catalog"), "Cached_rrc_requests"); + return (long) mBeanServer.getAttribute(new ObjectName("rubix:name=stats,type=detailed,catalog=catalog"), "Cached_rrc_requests"); } catch (Exception exception) { throw new RuntimeException(exception); @@ -583,7 +587,7 @@ private long getAsyncDownloadedMb(ReadMode readMode) } try { - return (long) BEAN_SERVER.getAttribute(new ObjectName("metrics:name=rubix.bookkeeper.count.async_downloaded_mb"), "Count"); + return (long) mBeanServer.getAttribute(new ObjectName("metrics:name=rubix.bookkeeper.count.async_downloaded_mb"), "Count"); } catch (Exception exception) { throw new RuntimeException(exception); diff --git a/plugin/trino-http-event-listener/src/test/java/io/trino/plugin/httpquery/TestHttpEventListener.java b/plugin/trino-http-event-listener/src/test/java/io/trino/plugin/httpquery/TestHttpEventListener.java index 6f270ff080a7e..b879861fb43c9 100644 --- a/plugin/trino-http-event-listener/src/test/java/io/trino/plugin/httpquery/TestHttpEventListener.java +++ b/plugin/trino-http-event-listener/src/test/java/io/trino/plugin/httpquery/TestHttpEventListener.java @@ -234,6 +234,7 @@ public void teardown() catch (IOException ignored) { // MockWebServer.close() method sometimes throws 'Gave up waiting for executor to shut down' } + server = null; } /** diff --git a/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/TestIcebergGcsConnectorSmokeTest.java b/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/TestIcebergGcsConnectorSmokeTest.java index 38f7f5ece9bf5..a8169f9c18883 100644 --- a/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/TestIcebergGcsConnectorSmokeTest.java +++ b/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/TestIcebergGcsConnectorSmokeTest.java @@ -57,23 +57,30 @@ public class TestIcebergGcsConnectorSmokeTest private static final Logger LOG = Logger.get(TestIcebergGcsConnectorSmokeTest.class); private static final FileAttribute READ_ONLY_PERMISSIONS = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-r--r--")); - private final String schema; private final String gcpStorageBucket; - private final Path gcpCredentialsFile; - private final HiveHadoop hiveHadoop; - private final FileSystem fileSystem; + private final String gcpCredentialKey; + private final String schema; + + private HiveHadoop hiveHadoop; + private FileSystem fileSystem; @Parameters({"testing.gcp-storage-bucket", "testing.gcp-credentials-key"}) public TestIcebergGcsConnectorSmokeTest(String gcpStorageBucket, String gcpCredentialKey) { super(ORC); - this.schema = "test_iceberg_gcs_connector_smoke_test_" + randomNameSuffix(); this.gcpStorageBucket = requireNonNull(gcpStorageBucket, "gcpStorageBucket is null"); + this.gcpCredentialKey = requireNonNull(gcpCredentialKey, "gcpCredentialKey is null"); + this.schema = "test_iceberg_gcs_connector_smoke_test_" + randomNameSuffix(); + } - requireNonNull(gcpCredentialKey, "gcpCredentialKey is null"); + @Override + protected QueryRunner createQueryRunner() + throws Exception + { InputStream jsonKey = new ByteArrayInputStream(Base64.getDecoder().decode(gcpCredentialKey)); + Path gcpCredentialsFile; try { - this.gcpCredentialsFile = Files.createTempFile("gcp-credentials", ".json", READ_ONLY_PERMISSIONS); + gcpCredentialsFile = Files.createTempFile("gcp-credentials", ".json", READ_ONLY_PERMISSIONS); gcpCredentialsFile.toFile().deleteOnExit(); Files.write(gcpCredentialsFile, jsonKey.readAllBytes()); @@ -104,6 +111,22 @@ public TestIcebergGcsConnectorSmokeTest(String gcpStorageBucket, String gcpCrede catch (URISyntaxException e) { throw new RuntimeException(e); } + + return IcebergQueryRunner.builder() + .setIcebergProperties(ImmutableMap.builder() + .put("iceberg.catalog.type", "hive_metastore") + .put("hive.gcs.json-key-file-path", gcpCredentialsFile.toAbsolutePath().toString()) + .put("hive.metastore.uri", "thrift://" + hiveHadoop.getHiveMetastoreEndpoint()) + .put("iceberg.file-format", format.name()) + .put("iceberg.register-table-procedure.enabled", "true") + .buildOrThrow()) + .setSchemaInitializer( + SchemaInitializer.builder() + .withClonedTpchTables(REQUIRED_TPCH_TABLES) + .withSchemaName(schema) + .withSchemaProperties(ImmutableMap.of("location", "'" + schemaUrl() + "'")) + .build()) + .build(); } @AfterClass(alwaysRun = true) @@ -117,6 +140,7 @@ public void removeTestData() // The GCS bucket should be configured to expire objects automatically. Clean up issues do not need to fail the test. LOG.warn(e, "Failed to clean up GCS test directory: %s", schemaUrl()); } + fileSystem = null; } } @@ -133,27 +157,6 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) } } - @Override - protected QueryRunner createQueryRunner() - throws Exception - { - return IcebergQueryRunner.builder() - .setIcebergProperties(ImmutableMap.builder() - .put("iceberg.catalog.type", "hive_metastore") - .put("hive.gcs.json-key-file-path", gcpCredentialsFile.toAbsolutePath().toString()) - .put("hive.metastore.uri", "thrift://" + hiveHadoop.getHiveMetastoreEndpoint()) - .put("iceberg.file-format", format.name()) - .put("iceberg.register-table-procedure.enabled", "true") - .buildOrThrow()) - .setSchemaInitializer( - SchemaInitializer.builder() - .withClonedTpchTables(REQUIRED_TPCH_TABLES) - .withSchemaName(schema) - .withSchemaProperties(ImmutableMap.of("location", "'" + schemaUrl() + "'")) - .build()) - .build(); - } - @Override protected String createSchemaSql(String schema) { diff --git a/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/TestIcebergGetTableStatisticsOperations.java b/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/TestIcebergGetTableStatisticsOperations.java index 34b96ab99039f..9780aa764cdd5 100644 --- a/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/TestIcebergGetTableStatisticsOperations.java +++ b/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/TestIcebergGetTableStatisticsOperations.java @@ -92,6 +92,9 @@ public void tearDown() throws IOException { deleteRecursively(metastoreDir.toPath(), ALLOW_INSECURE); + localQueryRunner.close(); + localQueryRunner = null; + metadata = null; } @BeforeMethod diff --git a/plugin/trino-kinesis/src/test/java/io/trino/plugin/kinesis/TestMinimalFunctionality.java b/plugin/trino-kinesis/src/test/java/io/trino/plugin/kinesis/TestMinimalFunctionality.java index f3fde7a124c0a..dcbd96d2d73d8 100644 --- a/plugin/trino-kinesis/src/test/java/io/trino/plugin/kinesis/TestMinimalFunctionality.java +++ b/plugin/trino-kinesis/src/test/java/io/trino/plugin/kinesis/TestMinimalFunctionality.java @@ -86,10 +86,11 @@ public void start(String accessKey, String secretKey) embeddedKinesisStream = new EmbeddedKinesisStream(TestUtils.noneToBlank(accessKey), TestUtils.noneToBlank(secretKey)); } - @AfterClass + @AfterClass(alwaysRun = true) public void stop() { embeddedKinesisStream.close(); + embeddedKinesisStream = null; } @Parameters({ @@ -175,5 +176,6 @@ public void tearDown() { embeddedKinesisStream.deleteStream(streamName); queryRunner.close(); + queryRunner = null; } } diff --git a/plugin/trino-kinesis/src/test/java/io/trino/plugin/kinesis/TestRecordAccess.java b/plugin/trino-kinesis/src/test/java/io/trino/plugin/kinesis/TestRecordAccess.java index eaf8f5433601b..420615d2acd37 100644 --- a/plugin/trino-kinesis/src/test/java/io/trino/plugin/kinesis/TestRecordAccess.java +++ b/plugin/trino-kinesis/src/test/java/io/trino/plugin/kinesis/TestRecordAccess.java @@ -79,14 +79,15 @@ public void start() jsonStreamName = "sampleTable"; jsonGzipCompressStreamName = "sampleGzipCompressTable"; jsonAutomaticCompressStreamName = "sampleAutomaticCompressTable"; - this.queryRunner = new StandaloneQueryRunner(SESSION); + queryRunner = new StandaloneQueryRunner(SESSION); mockClient = TestUtils.installKinesisPlugin(queryRunner); } - @AfterClass + @AfterClass(alwaysRun = true) public void stop() { queryRunner.close(); + queryRunner = null; } private void createDummyMessages(String streamName, int count) diff --git a/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/BaseKuduConnectorSmokeTest.java b/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/BaseKuduConnectorSmokeTest.java index f54d69c19787e..063ca1094b672 100644 --- a/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/BaseKuduConnectorSmokeTest.java +++ b/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/BaseKuduConnectorSmokeTest.java @@ -16,6 +16,7 @@ import io.trino.testing.BaseConnectorSmokeTest; import io.trino.testing.QueryRunner; import io.trino.testing.TestingConnectorBehavior; +import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import java.util.Optional; @@ -43,6 +44,13 @@ protected QueryRunner createQueryRunner() return createKuduQueryRunnerTpch(kuduServer, getKuduSchemaEmulationPrefix(), REQUIRED_TPCH_TABLES); } + @AfterClass(alwaysRun = true) + public void tearDown() + { + kuduServer.close(); + kuduServer = null; + } + @SuppressWarnings("DuplicateBranchesInSwitch") @Override protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) diff --git a/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/TestingKuduServer.java b/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/TestingKuduServer.java index a7128afc5b032..235c4062d1e78 100644 --- a/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/TestingKuduServer.java +++ b/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/TestingKuduServer.java @@ -16,6 +16,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.io.Closer; import com.google.common.net.HostAndPort; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; import org.testcontainers.containers.ToxiproxyContainer; @@ -50,6 +51,8 @@ public class TestingKuduServer private final GenericContainer master; private final List> tServers; + private boolean stopped; + public TestingKuduServer() { this(LATEST_TAG); @@ -120,6 +123,13 @@ public void close() catch (IOException e) { throw new RuntimeException(e); } + stopped = true; + } + + @ResourcePresence + public boolean isNotStopped() + { + return !stopped; } private static String getHostIPAddress() diff --git a/plugin/trino-mariadb/pom.xml b/plugin/trino-mariadb/pom.xml index 7c01a95efb28d..074da4bb7c383 100644 --- a/plugin/trino-mariadb/pom.xml +++ b/plugin/trino-mariadb/pom.xml @@ -123,6 +123,12 @@ test + + io.trino + trino-testing-services + test + + io.trino trino-tpch diff --git a/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestingMariaDbServer.java b/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestingMariaDbServer.java index a88e94a002e57..7c6c80cf80a56 100644 --- a/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestingMariaDbServer.java +++ b/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestingMariaDbServer.java @@ -13,6 +13,7 @@ */ package io.trino.plugin.mariadb; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.utility.DockerImageName; @@ -84,4 +85,10 @@ public void close() { container.close(); } + + @ResourcePresence + public boolean isRunning() + { + return container.getContainerId() != null; + } } diff --git a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/BaseMongoConnectorTest.java b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/BaseMongoConnectorTest.java index ec60550e6d0b4..38000bbcd877d 100644 --- a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/BaseMongoConnectorTest.java +++ b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/BaseMongoConnectorTest.java @@ -63,7 +63,9 @@ public abstract class BaseMongoConnectorTest public final void destroy() { server.close(); + server = null; client.close(); + client = null; } @SuppressWarnings("DuplicateBranchesInSwitch") diff --git a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/MongoServer.java b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/MongoServer.java index febb162ce07aa..8c08e465a4067 100644 --- a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/MongoServer.java +++ b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/MongoServer.java @@ -14,6 +14,7 @@ package io.trino.plugin.mongodb; import com.mongodb.ConnectionString; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.MongoDBContainer; import java.io.Closeable; @@ -47,4 +48,10 @@ public void close() { dockerContainer.close(); } + + @ResourcePresence + public boolean isRunning() + { + return dockerContainer.getContainerId() != null; + } } diff --git a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoConnectorTest.java b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoConnectorTest.java index 3f2a27baaf916..6c77cb464fbb2 100644 --- a/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoConnectorTest.java +++ b/plugin/trino-mongodb/src/test/java/io/trino/plugin/mongodb/TestMongoConnectorTest.java @@ -26,7 +26,7 @@ public class TestMongoConnectorTest protected QueryRunner createQueryRunner() throws Exception { - server = closeAfterClass(new MongoServer()); + server = new MongoServer(); client = createMongoClient(server); return createMongoQueryRunner(server, ImmutableMap.of(), REQUIRED_TPCH_TABLES); } diff --git a/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestingMySqlServer.java b/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestingMySqlServer.java index 973f86c9b8db4..86af2417c9024 100644 --- a/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestingMySqlServer.java +++ b/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestingMySqlServer.java @@ -13,6 +13,7 @@ */ package io.trino.plugin.mysql; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.MySQLContainer; import java.io.Closeable; @@ -117,4 +118,10 @@ public void close() throw new UncheckedIOException(e); } } + + @ResourcePresence + public boolean isRunning() + { + return container.getContainerId() != null; + } } diff --git a/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/TestingOracleServer.java b/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/TestingOracleServer.java index 67b849dd75603..0e412d7b152b9 100644 --- a/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/TestingOracleServer.java +++ b/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/TestingOracleServer.java @@ -21,6 +21,7 @@ import io.trino.plugin.jdbc.DriverConnectionFactory; import io.trino.plugin.jdbc.RetryingConnectionFactory; import io.trino.plugin.jdbc.credential.StaticCredentialProvider; +import io.trino.testing.ResourcePresence; import net.jodah.failsafe.Failsafe; import net.jodah.failsafe.RetryPolicy; import oracle.jdbc.OracleDriver; @@ -132,4 +133,10 @@ public void close() { container.stop(); } + + @ResourcePresence + public boolean isRunning() + { + return container.getContainerId() != null; + } } diff --git a/plugin/trino-password-authenticators/src/test/java/io/trino/plugin/password/ldap/TestLdapAuthenticator.java b/plugin/trino-password-authenticators/src/test/java/io/trino/plugin/password/ldap/TestLdapAuthenticator.java index c65b63e089d40..0272fd13226ec 100644 --- a/plugin/trino-password-authenticators/src/test/java/io/trino/plugin/password/ldap/TestLdapAuthenticator.java +++ b/plugin/trino-password-authenticators/src/test/java/io/trino/plugin/password/ldap/TestLdapAuthenticator.java @@ -31,7 +31,7 @@ public class TestLdapAuthenticator { - private final Closer closer = Closer.create(); + private Closer closer; private TestingOpenLdapServer openLdapServer; private LdapAuthenticatorClient client; @@ -40,11 +40,11 @@ public class TestLdapAuthenticator public void setup() throws Exception { + closer = Closer.create(); Network network = Network.newNetwork(); closer.register(network::close); - openLdapServer = new TestingOpenLdapServer(network); - closer.register(openLdapServer); + openLdapServer = closer.register(new TestingOpenLdapServer(network)); openLdapServer.start(); client = new LdapAuthenticatorClient( @@ -57,6 +57,9 @@ public void close() throws Exception { closer.close(); + closer = null; + openLdapServer = null; + client = null; } @Test diff --git a/plugin/trino-password-authenticators/src/test/java/io/trino/plugin/password/ldap/TestLdapAuthenticatorWithTimeouts.java b/plugin/trino-password-authenticators/src/test/java/io/trino/plugin/password/ldap/TestLdapAuthenticatorWithTimeouts.java index 4c9df0e33b3cb..7e5e7ca08b9dd 100644 --- a/plugin/trino-password-authenticators/src/test/java/io/trino/plugin/password/ldap/TestLdapAuthenticatorWithTimeouts.java +++ b/plugin/trino-password-authenticators/src/test/java/io/trino/plugin/password/ldap/TestLdapAuthenticatorWithTimeouts.java @@ -35,7 +35,7 @@ public class TestLdapAuthenticatorWithTimeouts { - private final Closer closer = Closer.create(); + private Closer closer; private TestingOpenLdapServer openLdapServer; private String proxyLdapUrl; @@ -44,6 +44,7 @@ public class TestLdapAuthenticatorWithTimeouts public void setup() throws Exception { + closer = Closer.create(); Network network = Network.newNetwork(); closer.register(network::close); @@ -52,8 +53,7 @@ public void setup() closer.register(proxyServer::close); proxyServer.start(); - openLdapServer = new TestingOpenLdapServer(network); - closer.register(openLdapServer); + openLdapServer = closer.register(new TestingOpenLdapServer(network)); openLdapServer.start(); ContainerProxy proxy = proxyServer.getProxy(openLdapServer.getNetworkAlias(), LDAP_PORT); @@ -67,6 +67,9 @@ public void close() throws Exception { closer.close(); + closer = null; + openLdapServer = null; + proxyLdapUrl = null; } @Test diff --git a/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestingPhoenixServer.java b/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestingPhoenixServer.java index 38071c89587f8..1ac6a53912bb7 100644 --- a/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestingPhoenixServer.java +++ b/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestingPhoenixServer.java @@ -14,6 +14,7 @@ package io.trino.plugin.phoenix5; import io.airlift.log.Logger; +import io.trino.testng.services.ManageTestResources; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HBaseTestingUtility; @@ -31,6 +32,7 @@ import static org.apache.hadoop.hbase.HConstants.MASTER_INFO_PORT; import static org.apache.hadoop.hbase.HConstants.REGIONSERVER_INFO_PORT; +@ManageTestResources.Suppress(because = "The actual server is kept on a static field and instance of this class is used for reference counting only") public final class TestingPhoenixServer { private static final Logger LOG = Logger.get(TestingPhoenixServer.class); diff --git a/plugin/trino-postgresql/src/test/java/io/trino/plugin/postgresql/TestingPostgreSqlServer.java b/plugin/trino-postgresql/src/test/java/io/trino/plugin/postgresql/TestingPostgreSqlServer.java index 28ab9168a7dcb..f62a92f15ccb9 100644 --- a/plugin/trino-postgresql/src/test/java/io/trino/plugin/postgresql/TestingPostgreSqlServer.java +++ b/plugin/trino-postgresql/src/test/java/io/trino/plugin/postgresql/TestingPostgreSqlServer.java @@ -15,6 +15,7 @@ import com.google.common.collect.ImmutableList; import io.trino.plugin.jdbc.RemoteDatabaseEvent; +import io.trino.testing.ResourcePresence; import org.intellij.lang.annotations.Language; import org.testcontainers.containers.PostgreSQLContainer; @@ -164,6 +165,12 @@ public void close() dockerContainer.close(); } + @ResourcePresence + public boolean isRunning() + { + return dockerContainer.getContainerId() != null; + } + public static class DatabaseEventsRecorder { private final Supplier> loggedQueriesSource; diff --git a/plugin/trino-prometheus/pom.xml b/plugin/trino-prometheus/pom.xml index c60bfa1b66210..6b91dbffae438 100644 --- a/plugin/trino-prometheus/pom.xml +++ b/plugin/trino-prometheus/pom.xml @@ -181,6 +181,12 @@ + + io.trino + trino-testing-services + test + + io.airlift http-server diff --git a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/PrometheusServer.java b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/PrometheusServer.java index df938c126f6c7..b524fee222c22 100644 --- a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/PrometheusServer.java +++ b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/PrometheusServer.java @@ -13,6 +13,7 @@ */ package io.trino.plugin.prometheus; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; @@ -67,4 +68,10 @@ public void close() { dockerContainer.close(); } + + @ResourcePresence + public boolean isRunning() + { + return dockerContainer.getContainerId() != null; + } } diff --git a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusCaseInsensitiveNameMatching.java b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusCaseInsensitiveNameMatching.java index 8bc744306441e..f584a68a99c49 100644 --- a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusCaseInsensitiveNameMatching.java +++ b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusCaseInsensitiveNameMatching.java @@ -48,6 +48,7 @@ public void tearDown() { if (prometheusHttpServer != null) { prometheusHttpServer.stop(); + prometheusHttpServer = null; } } diff --git a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryMatrixResponseParse.java b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryMatrixResponseParse.java index 69796938df55f..cc1c2eeb9ad03 100644 --- a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryMatrixResponseParse.java +++ b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryMatrixResponseParse.java @@ -15,6 +15,7 @@ import com.google.common.io.Resources; import io.trino.spi.TrinoException; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -86,4 +87,14 @@ public void setUp() assertNotNull(promMatrixResponse, "metadataUrl is null"); this.promErrorResponse = promErrorResponse.openStream(); } + + @AfterMethod(alwaysRun = true) + public void tearDown() + throws Exception + { + promMatrixResponse.close(); + promMatrixResponse = null; + promErrorResponse.close(); + promErrorResponse = null; + } } diff --git a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryScalarResponseParse.java b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryScalarResponseParse.java index 64bce25df5b61..d2e4d6de62f7f 100644 --- a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryScalarResponseParse.java +++ b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryScalarResponseParse.java @@ -14,6 +14,7 @@ package io.trino.plugin.prometheus; import com.google.common.io.Resources; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -71,4 +72,12 @@ public void setUp() assertNotNull(promMatrixResponse, "metadataUrl is null"); this.promVectorResponse = promMatrixResponse.openStream(); } + + @AfterMethod(alwaysRun = true) + public void tearDown() + throws Exception + { + promVectorResponse.close(); + promVectorResponse = null; + } } diff --git a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryVectorResponseParse.java b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryVectorResponseParse.java index cde81ecaaaf69..15b1f7a516297 100644 --- a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryVectorResponseParse.java +++ b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusQueryVectorResponseParse.java @@ -14,6 +14,7 @@ package io.trino.plugin.prometheus; import com.google.common.io.Resources; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -71,4 +72,12 @@ public void setUp() assertNotNull(promMatrixResponse, "metadataUrl is null"); this.promVectorResponse = promMatrixResponse.openStream(); } + + @AfterMethod(alwaysRun = true) + public void tearDown() + throws Exception + { + promVectorResponse.close(); + promVectorResponse = null; + } } diff --git a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusRecordSet.java b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusRecordSet.java index 7405ec17b4cf3..bb84a880406d9 100644 --- a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusRecordSet.java +++ b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusRecordSet.java @@ -105,6 +105,7 @@ public void tearDown() { if (prometheusHttpServer != null) { prometheusHttpServer.stop(); + prometheusHttpServer = null; } } } diff --git a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusRecordSetProvider.java b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusRecordSetProvider.java index e87e9bb82e0ea..a332939f5bcc3 100644 --- a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusRecordSetProvider.java +++ b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusRecordSetProvider.java @@ -57,6 +57,7 @@ public void tearDown() { if (prometheusHttpServer != null) { prometheusHttpServer.stop(); + prometheusHttpServer = null; } } diff --git a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusSplit.java b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusSplit.java index f7ba4b8b1cdd7..a51309acf5a45 100644 --- a/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusSplit.java +++ b/plugin/trino-prometheus/src/test/java/io/trino/plugin/prometheus/TestPrometheusSplit.java @@ -28,6 +28,7 @@ import io.trino.spi.predicate.TupleDomain; import io.trino.spi.predicate.ValueSet; import org.apache.http.NameValuePair; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -76,6 +77,13 @@ public void setUp() prometheusHttpServer = new PrometheusHttpServer(); } + @AfterClass(alwaysRun = true) + public void tearDown() + { + prometheusHttpServer.stop(); + prometheusHttpServer = null; + } + @Test public void testAddresses() { diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/TestRaptorConnector.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/TestRaptorConnector.java index 4518b7e67de8a..109c537070108 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/TestRaptorConnector.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/TestRaptorConnector.java @@ -120,6 +120,7 @@ public void tearDown() throws Exception { dummyHandle.close(); + dummyHandle = null; deleteRecursively(dataDir.toPath(), ALLOW_INSECURE); } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/TestRaptorMySqlConnectorTest.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/TestRaptorMySqlConnectorTest.java index eca2c6aacd02f..c84abaf2585f5 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/TestRaptorMySqlConnectorTest.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/TestRaptorMySqlConnectorTest.java @@ -45,6 +45,7 @@ protected QueryRunner createQueryRunner() public final void destroy() { mysqlContainer.close(); + mysqlContainer = null; } private static String getJdbcUrl(MySQLContainer container) diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestDatabaseShardManager.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestDatabaseShardManager.java index bd44fd59bf7b7..8545f69803354 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestDatabaseShardManager.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestDatabaseShardManager.java @@ -117,6 +117,7 @@ public void teardown() throws IOException { dummyHandle.close(); + dummyHandle = null; deleteRecursively(dataDir.toPath(), ALLOW_INSECURE); } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestMetadataDao.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestMetadataDao.java index eadd36decd298..4f76bef29c41b 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestMetadataDao.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestMetadataDao.java @@ -48,6 +48,7 @@ public void setup() public void tearDown() { dummyHandle.close(); + dummyHandle = null; } @Test diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestRaptorMetadata.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestRaptorMetadata.java index 803a24521a39d..c227b5ede6106 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestRaptorMetadata.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestRaptorMetadata.java @@ -112,6 +112,7 @@ public void setupDatabase() public void cleanupDatabase() { dummyHandle.close(); + dummyHandle = null; } @Test diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestRaptorSplitManager.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestRaptorSplitManager.java index 673a833c11616..0f34b1f285bd8 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestRaptorSplitManager.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestRaptorSplitManager.java @@ -133,6 +133,7 @@ public void teardown() throws IOException { dummyHandle.close(); + dummyHandle = null; deleteRecursively(temporary, ALLOW_INSECURE); } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestShardCleaner.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestShardCleaner.java index e41e4d38f9bf0..a8575a2f5e5fd 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestShardCleaner.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestShardCleaner.java @@ -111,6 +111,7 @@ public void teardown() { if (dummyHandle != null) { dummyHandle.close(); + dummyHandle = null; } deleteRecursively(temporary, ALLOW_INSECURE); } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestShardDao.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestShardDao.java index 3ce08855a603c..485ca7741af25 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestShardDao.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/metadata/TestShardDao.java @@ -57,6 +57,7 @@ public void setup() public void teardown() { dummyHandle.close(); + dummyHandle = null; } @Test diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestBucketBalancer.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestBucketBalancer.java index c34bc29bd5aac..33db3766f939d 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestBucketBalancer.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestBucketBalancer.java @@ -86,6 +86,7 @@ public void teardown() { if (dummyHandle != null) { dummyHandle.close(); + dummyHandle = null; } } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestRaptorStorageManager.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestRaptorStorageManager.java index 1974226dec3fa..5fc446f623bb1 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestRaptorStorageManager.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestRaptorStorageManager.java @@ -165,6 +165,7 @@ public void tearDown() { if (dummyHandle != null) { dummyHandle.close(); + dummyHandle = null; } deleteRecursively(temporary, ALLOW_INSECURE); } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestShardEjector.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestShardEjector.java index 8e39982bd67a8..5efdbbb752e37 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestShardEjector.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestShardEjector.java @@ -88,6 +88,7 @@ public void teardown() { if (dummyHandle != null) { dummyHandle.close(); + dummyHandle = null; } if (dataDir != null) { deleteRecursively(dataDir, ALLOW_INSECURE); diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestShardRecovery.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestShardRecovery.java index 3371dad4360ac..2a98d916d6a2a 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestShardRecovery.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/TestShardRecovery.java @@ -88,6 +88,7 @@ public void tearDown() { if (dummyHandle != null) { dummyHandle.close(); + dummyHandle = null; } deleteRecursively(temporary, ALLOW_INSECURE); } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardCompactor.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardCompactor.java index 426b551bf4b37..e6191b8ff6124 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardCompactor.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardCompactor.java @@ -101,6 +101,7 @@ public void tearDown() { if (dummyHandle != null) { dummyHandle.close(); + dummyHandle = null; } deleteRecursively(temporary, ALLOW_INSECURE); } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardOrganizationManager.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardOrganizationManager.java index 32a4271e4699e..9a875396d5281 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardOrganizationManager.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardOrganizationManager.java @@ -77,6 +77,7 @@ public void setup() public void teardown() { dummyHandle.close(); + dummyHandle = null; } @Test diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardOrganizerUtil.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardOrganizerUtil.java index 97aefbe25d17b..32d0b4e2dda3d 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardOrganizerUtil.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/storage/organization/TestShardOrganizerUtil.java @@ -94,6 +94,7 @@ public void teardown() throws Exception { dummyHandle.close(); + dummyHandle = null; deleteRecursively(dataDir.toPath(), ALLOW_INSECURE); } diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/systemtables/TestShardMetadataRecordCursor.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/systemtables/TestShardMetadataRecordCursor.java index c94c67e1b574d..3753f3a02075a 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/systemtables/TestShardMetadataRecordCursor.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/systemtables/TestShardMetadataRecordCursor.java @@ -92,6 +92,7 @@ public void setup() public void teardown() { dummyHandle.close(); + dummyHandle = null; } @Test diff --git a/plugin/trino-session-property-managers/src/test/java/io/trino/plugin/session/db/TestDbSessionPropertyManager.java b/plugin/trino-session-property-managers/src/test/java/io/trino/plugin/session/db/TestDbSessionPropertyManager.java index 46f8c113ba5c2..c3e54d178e3f7 100644 --- a/plugin/trino-session-property-managers/src/test/java/io/trino/plugin/session/db/TestDbSessionPropertyManager.java +++ b/plugin/trino-session-property-managers/src/test/java/io/trino/plugin/session/db/TestDbSessionPropertyManager.java @@ -80,6 +80,7 @@ public void destroy() { specsProvider.destroy(); mysqlContainer.close(); + mysqlContainer = null; } @Override diff --git a/plugin/trino-session-property-managers/src/test/java/io/trino/plugin/session/db/TestDbSessionPropertyManagerIntegration.java b/plugin/trino-session-property-managers/src/test/java/io/trino/plugin/session/db/TestDbSessionPropertyManagerIntegration.java index 59b012c3ddded..cd597095a8b43 100644 --- a/plugin/trino-session-property-managers/src/test/java/io/trino/plugin/session/db/TestDbSessionPropertyManagerIntegration.java +++ b/plugin/trino-session-property-managers/src/test/java/io/trino/plugin/session/db/TestDbSessionPropertyManagerIntegration.java @@ -102,6 +102,8 @@ public void destroy() closer.register(queryRunner); closer.register(mysqlContainer::close); } + queryRunner = null; + mysqlContainer = null; } @BeforeMethod diff --git a/plugin/trino-singlestore/pom.xml b/plugin/trino-singlestore/pom.xml index 3815baf095ea4..06c7e1b49ec99 100644 --- a/plugin/trino-singlestore/pom.xml +++ b/plugin/trino-singlestore/pom.xml @@ -134,6 +134,12 @@ test + + io.trino + trino-testing-services + test + + io.trino trino-tpch diff --git a/plugin/trino-singlestore/src/test/java/io/trino/plugin/singlestore/TestingSingleStoreServer.java b/plugin/trino-singlestore/src/test/java/io/trino/plugin/singlestore/TestingSingleStoreServer.java index 8e0ee1acb38eb..ec6f4d89e5957 100644 --- a/plugin/trino-singlestore/src/test/java/io/trino/plugin/singlestore/TestingSingleStoreServer.java +++ b/plugin/trino-singlestore/src/test/java/io/trino/plugin/singlestore/TestingSingleStoreServer.java @@ -14,6 +14,7 @@ package io.trino.plugin.singlestore; import com.google.common.collect.ImmutableSet; +import io.trino.testing.ResourcePresence; import org.testcontainers.containers.JdbcDatabaseContainer; import org.testcontainers.utility.DockerImageName; @@ -46,11 +47,11 @@ public TestingSingleStoreServer(String dockerImageName) addEnv("ROOT_PASSWORD", "memsql_root_password"); withCommand("sh", "-xeuc", "/startup && " + - // Lower the size of pre-allocated log files to 1MB (minimum allowed) to reduce disk footprint - "memsql-admin update-config --yes --all --set-global --key \"log_file_size_partitions\" --value \"1048576\" && " + - "memsql-admin update-config --yes --all --set-global --key \"log_file_size_ref_dbs\" --value \"1048576\" && " + - // re-execute startup to actually start the nodes (first run performs setup but doesn't start the nodes) - "exec /startup"); + // Lower the size of pre-allocated log files to 1MB (minimum allowed) to reduce disk footprint + "memsql-admin update-config --yes --all --set-global --key \"log_file_size_partitions\" --value \"1048576\" && " + + "memsql-admin update-config --yes --all --set-global --key \"log_file_size_ref_dbs\" --value \"1048576\" && " + + // re-execute startup to actually start the nodes (first run performs setup but doesn't start the nodes) + "exec /startup"); start(); } @@ -103,6 +104,12 @@ public void execute(String sql) execute(sql, getUsername(), getPassword()); } + @ResourcePresence + public boolean isResourcePresent() + { + return isRunning() || getContainerId() != null; + } + public void execute(String sql, String user, String password) { try (Connection connection = DriverManager.getConnection(getJdbcUrl(), user, password); diff --git a/plugin/trino-sqlserver/src/test/java/io/trino/plugin/sqlserver/TestingSqlServer.java b/plugin/trino-sqlserver/src/test/java/io/trino/plugin/sqlserver/TestingSqlServer.java index ebf622c699e80..8eacba7ccaf26 100644 --- a/plugin/trino-sqlserver/src/test/java/io/trino/plugin/sqlserver/TestingSqlServer.java +++ b/plugin/trino-sqlserver/src/test/java/io/trino/plugin/sqlserver/TestingSqlServer.java @@ -14,6 +14,7 @@ package io.trino.plugin.sqlserver; import io.airlift.log.Logger; +import io.trino.testing.ResourcePresence; import io.trino.testing.sql.SqlExecutor; import net.jodah.failsafe.Failsafe; import net.jodah.failsafe.RetryPolicy; @@ -213,6 +214,12 @@ public void close() } } + @ResourcePresence + public boolean isRunning() + { + return container.getContainerId() != null; + } + private static class InitializedState { private final MSSQLServerContainer container; diff --git a/plugin/trino-thrift/src/test/java/io/trino/plugin/thrift/integration/TestThriftProjectionPushdown.java b/plugin/trino-thrift/src/test/java/io/trino/plugin/thrift/integration/TestThriftProjectionPushdown.java index 42d59a8f00ae9..32dc1009dc22e 100644 --- a/plugin/trino-thrift/src/test/java/io/trino/plugin/thrift/integration/TestThriftProjectionPushdown.java +++ b/plugin/trino-thrift/src/test/java/io/trino/plugin/thrift/integration/TestThriftProjectionPushdown.java @@ -107,7 +107,7 @@ protected Optional createLocalQueryRunner() return Optional.of(runner); } - @AfterClass + @AfterClass(alwaysRun = true) public void cleanup() { if (servers != null) { diff --git a/service/trino-proxy/src/test/java/io/trino/proxy/TestProxyServer.java b/service/trino-proxy/src/test/java/io/trino/proxy/TestProxyServer.java index 9114680172c34..565569883684a 100644 --- a/service/trino-proxy/src/test/java/io/trino/proxy/TestProxyServer.java +++ b/service/trino-proxy/src/test/java/io/trino/proxy/TestProxyServer.java @@ -113,8 +113,10 @@ public void tearDownServer() throws IOException { server.close(); + server = null; lifeCycleManager.stop(); executorService.shutdownNow(); + executorService = null; Files.delete(sharedSecretFile); } diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestImpersonation.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestImpersonation.java index 16b6255b1a6ba..857064506633c 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestImpersonation.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestImpersonation.java @@ -15,6 +15,7 @@ import com.google.inject.Inject; import com.google.inject.name.Named; +import io.trino.tempto.AfterTestWithContext; import io.trino.tempto.BeforeTestWithContext; import io.trino.tempto.ProductTest; import io.trino.tempto.hadoop.hdfs.HdfsClient; @@ -57,6 +58,13 @@ public void setup() aliceExecutor = connectToTrino("alice@presto"); } + @AfterTestWithContext + public void cleanup() + { + // should not be closed, this would close a shared, global QueryExecutor + aliceExecutor = null; + } + @Test(groups = {HDFS_NO_IMPERSONATION, PROFILE_SPECIFIC_TESTS}) public void testHdfsImpersonationDisabled() { diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestSqlCancel.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestSqlCancel.java index 44ee6569b40ea..5e05dee988f8b 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestSqlCancel.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestSqlCancel.java @@ -79,7 +79,10 @@ public void setUp() public void cleanUp() throws IOException { + queryCanceller = null; // closed via closer + executor = null; // closed via closer closer.close(); + closer = null; } @Test(groups = CANCEL_QUERY, timeOut = 60_000L) diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/deltalake/BaseTestDeltaLakeMinioReads.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/deltalake/BaseTestDeltaLakeMinioReads.java index d0ada2cf55213..2b004bfc15c30 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/deltalake/BaseTestDeltaLakeMinioReads.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/deltalake/BaseTestDeltaLakeMinioReads.java @@ -67,6 +67,7 @@ public void tearDown() { deleteNotificationsTable(NOTIFICATIONS_TABLE); client.close(); + client = null; } @Test(groups = {DELTA_LAKE_MINIO, PROFILE_SPECIFIC_TESTS}) diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestGrantRevoke.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestGrantRevoke.java index d226f660837ea..555f10392fad5 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestGrantRevoke.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestGrantRevoke.java @@ -88,6 +88,11 @@ public void cleanup() aliceExecutor.executeQuery(format("DROP TABLE IF EXISTS %s", tableName)); aliceExecutor.executeQuery(format("DROP VIEW IF EXISTS %s", viewName)); cleanupRoles(); + + // should not be closed, this would close a shared, global QueryExecutor + aliceExecutor = null; + bobExecutor = null; + charlieExecutor = null; } @Test(groups = {AUTHORIZATION, PROFILE_SPECIFIC_TESTS}) diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestHiveTransactionalTable.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestHiveTransactionalTable.java index ece95eca8cdc9..bdbe4f219225d 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestHiveTransactionalTable.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestHiveTransactionalTable.java @@ -1831,8 +1831,7 @@ public void testFilesForAbortedTransactionsIgnored() "STORED AS ORC " + "TBLPROPERTIES ('transactional'='true')"); - ThriftMetastoreClient client = testHiveMetastoreClientFactory.createMetastoreClient(); - try { + try (ThriftMetastoreClient client = testHiveMetastoreClientFactory.createMetastoreClient()) { String selectFromOnePartitionsSql = "SELECT col FROM " + tableName + " ORDER BY COL"; // Create `delta-A` file @@ -1873,7 +1872,6 @@ public void testFilesForAbortedTransactionsIgnored() assertThat(onePartitionQueryResult).containsOnly(row(1), row(1), row(2), row(2)); } finally { - client.close(); onHive().executeQuery("DROP TABLE " + tableName); } } diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestSqlStandardAccessControlChecks.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestSqlStandardAccessControlChecks.java index 214704cfb5130..a58506bcf1462 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestSqlStandardAccessControlChecks.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestSqlStandardAccessControlChecks.java @@ -13,6 +13,7 @@ */ package io.trino.tests.product.hive; +import io.trino.tempto.AfterTestWithContext; import io.trino.tempto.BeforeTestWithContext; import io.trino.tempto.ProductTest; import io.trino.tempto.query.QueryExecutor; @@ -52,6 +53,16 @@ public void setup() aliceExecutor.executeQuery(format("CREATE VIEW %s AS SELECT month, day FROM %s", viewName, tableName)); } + @AfterTestWithContext + public void cleanup() + { + // should not be closed, this would close a shared, global QueryExecutor + aliceExecutor = null; + bobExecutor = null; + charlieExecutor = null; + caseSensitiveUserNameExecutor = null; + } + @Test(groups = {AUTHORIZATION, PROFILE_SPECIFIC_TESTS}) public void testAccessControlSelect() { diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergSparkCompatibility.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergSparkCompatibility.java index 6bcc31d6c6e97..4c534f9c0aaa5 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergSparkCompatibility.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergSparkCompatibility.java @@ -18,6 +18,7 @@ import com.google.common.collect.Streams; import io.airlift.concurrent.MoreFutures; import io.trino.plugin.hive.metastore.thrift.ThriftMetastoreClient; +import io.trino.tempto.AfterTestWithContext; import io.trino.tempto.BeforeTestWithContext; import io.trino.tempto.ProductTest; import io.trino.tempto.hadoop.hdfs.HdfsClient; @@ -98,6 +99,13 @@ public void setup() metastoreClient = testHiveMetastoreClientFactory.createMetastoreClient(); } + @AfterTestWithContext + public void tearDown() + { + metastoreClient.close(); + metastoreClient = null; + } + // see spark-defaults.conf private static final String SPARK_CATALOG = "iceberg_test"; private static final String TRINO_CATALOG = "iceberg"; diff --git a/testing/trino-test-jdbc-compatibility-old-driver/src/test/java/io/trino/TestJdbcCompatibility.java b/testing/trino-test-jdbc-compatibility-old-driver/src/test/java/io/trino/TestJdbcCompatibility.java index ef06cfe668bdd..61b65583b613b 100644 --- a/testing/trino-test-jdbc-compatibility-old-driver/src/test/java/io/trino/TestJdbcCompatibility.java +++ b/testing/trino-test-jdbc-compatibility-old-driver/src/test/java/io/trino/TestJdbcCompatibility.java @@ -105,6 +105,7 @@ public void tearDown() throws IOException { server.close(); + server = null; } @Test diff --git a/testing/trino-testing-containers/pom.xml b/testing/trino-testing-containers/pom.xml index 5d2f87091b696..7c49c5032e154 100644 --- a/testing/trino-testing-containers/pom.xml +++ b/testing/trino-testing-containers/pom.xml @@ -17,6 +17,11 @@ + + io.trino + trino-testing-services + + io.airlift log diff --git a/testing/trino-testing-containers/src/main/java/io/trino/testing/containers/BaseTestContainer.java b/testing/trino-testing-containers/src/main/java/io/trino/testing/containers/BaseTestContainer.java index 66f17bcd045a4..56723143b87b7 100644 --- a/testing/trino-testing-containers/src/main/java/io/trino/testing/containers/BaseTestContainer.java +++ b/testing/trino-testing-containers/src/main/java/io/trino/testing/containers/BaseTestContainer.java @@ -17,6 +17,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.net.HostAndPort; import io.airlift.log.Logger; +import io.trino.testing.ResourcePresence; import net.jodah.failsafe.Failsafe; import net.jodah.failsafe.RetryPolicy; import org.testcontainers.containers.Container; @@ -163,6 +164,12 @@ public void close() stop(); } + @ResourcePresence + public boolean isPresent() + { + return container.isRunning() || container.getContainerId() != null; + } + protected abstract static class Builder, BUILD extends BaseTestContainer> { protected String image; diff --git a/testing/trino-testing-kafka/pom.xml b/testing/trino-testing-kafka/pom.xml index 0693f52e0ea8b..91a2e30996ef0 100644 --- a/testing/trino-testing-kafka/pom.xml +++ b/testing/trino-testing-kafka/pom.xml @@ -17,6 +17,11 @@ + + io.trino + trino-testing-services + + io.airlift log diff --git a/testing/trino-testing-kafka/src/main/java/io/trino/testing/kafka/TestingKafka.java b/testing/trino-testing-kafka/src/main/java/io/trino/testing/kafka/TestingKafka.java index 0b5ce0de45a13..facaecb6f0ebe 100644 --- a/testing/trino-testing-kafka/src/main/java/io/trino/testing/kafka/TestingKafka.java +++ b/testing/trino-testing-kafka/src/main/java/io/trino/testing/kafka/TestingKafka.java @@ -17,6 +17,7 @@ import com.google.common.io.Closer; import com.google.common.util.concurrent.Futures; import io.airlift.log.Logger; +import io.trino.testing.ResourcePresence; import net.jodah.failsafe.Failsafe; import net.jodah.failsafe.RetryPolicy; import org.apache.kafka.clients.producer.KafkaProducer; @@ -46,6 +47,7 @@ import java.util.concurrent.Future; import java.util.stream.Stream; +import static com.google.common.base.Preconditions.checkState; import static java.lang.String.format; import static java.time.temporal.ChronoUnit.MILLIS; import static org.testcontainers.containers.KafkaContainer.KAFKA_PORT; @@ -67,6 +69,7 @@ public final class TestingKafka private final GenericContainer schemaRegistry; private final boolean withSchemaRegistry; private final Closer closer = Closer.create(); + private boolean stopped; public static TestingKafka create() { @@ -130,6 +133,7 @@ private TestingKafka(String confluentPlatformVersion, boolean withSchemaRegistry public void start() { + checkState(!stopped, "Cannot start again"); kafka.start(); if (withSchemaRegistry) { schemaRegistry.start(); @@ -141,6 +145,13 @@ public void close() throws IOException { closer.close(); + stopped = true; + } + + @ResourcePresence + public boolean isNotStopped() + { + return !stopped; } public void createTopic(String topic) diff --git a/testing/trino-testing-services/pom.xml b/testing/trino-testing-services/pom.xml index baee98e12d017..c9615749be101 100644 --- a/testing/trino-testing-services/pom.xml +++ b/testing/trino-testing-services/pom.xml @@ -37,6 +37,12 @@ jsr305 + + com.google.errorprone + error_prone_annotations + true + + com.google.guava guava diff --git a/testing/trino-testing-services/src/main/java/io/trino/testing/ResourcePresence.java b/testing/trino-testing-services/src/main/java/io/trino/testing/ResourcePresence.java new file mode 100644 index 0000000000000..9ac7c51fb0fa0 --- /dev/null +++ b/testing/trino-testing-services/src/main/java/io/trino/testing/ResourcePresence.java @@ -0,0 +1,29 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.testing; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Specifies a method that determines whether given resource-like class currently holds on to resources. + * The annotated method must not take parameters and must return a boolean, {@code true} indicating + * that a resource is present. + */ +@Retention(RUNTIME) +@Target(METHOD) +public @interface ResourcePresence {} diff --git a/testing/trino-testing-services/src/main/java/io/trino/testng/services/Listeners.java b/testing/trino-testing-services/src/main/java/io/trino/testng/services/Listeners.java index 80387347f5910..0b26c0512405c 100644 --- a/testing/trino-testing-services/src/main/java/io/trino/testng/services/Listeners.java +++ b/testing/trino-testing-services/src/main/java/io/trino/testng/services/Listeners.java @@ -13,6 +13,7 @@ */ package io.trino.testng.services; +import com.google.errorprone.annotations.FormatMethod; import org.testng.ITestNGListener; import static java.lang.String.format; @@ -26,6 +27,7 @@ private Listeners() {} * * @apiNote A TestNG listener cannot throw an exception, as this are not currently properly handled by TestNG. */ + @FormatMethod public static void reportListenerFailure(Class listenerClass, String format, Object... args) { System.err.println(format("FATAL: %s: ", listenerClass.getName()) + format(format, args)); diff --git a/testing/trino-testing-services/src/main/java/io/trino/testng/services/ManageTestResources.java b/testing/trino-testing-services/src/main/java/io/trino/testng/services/ManageTestResources.java new file mode 100644 index 0000000000000..8a2d29a2f9225 --- /dev/null +++ b/testing/trino-testing-services/src/main/java/io/trino/testng/services/ManageTestResources.java @@ -0,0 +1,369 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.testng.services; + +import com.google.common.collect.ImmutableList; +import io.airlift.log.Logger; +import io.trino.testing.ResourcePresence; +import org.intellij.lang.annotations.Language; +import org.testng.ITestClass; +import org.testng.ITestContext; +import org.testng.ITestListener; +import org.testng.ITestNGMethod; +import org.testng.ITestResult; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.reflect.Field; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Throwables.getStackTraceAsString; +import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static com.google.common.collect.MoreCollectors.toOptional; +import static io.trino.testng.services.Listeners.reportListenerFailure; +import static io.trino.testng.services.ManageTestResources.Stage.AFTER_CLASS; +import static io.trino.testng.services.ManageTestResources.Stage.BEFORE_CLASS; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.lang.reflect.Modifier.isStatic; + +public class ManageTestResources + implements ITestListener +{ + private static final Logger log = Logger.get(ManageTestResources.class); + + private final boolean enabled; + private final List rules; + + public ManageTestResources() + { + enabled = isEnabled(); + if (!enabled) { + log.info("ManageTestResources is disabled!"); + rules = List.of(); + return; + } + + ImmutableList.Builder rules = ImmutableList.builder(); + + // E.g. io.trino.testing.QueryRunner, io.trino.sql.query.QueryAssertions + rules.add(isAutoCloseable()); + + isInstanceTransactionManagerField().ifPresent(rules::add); + + // any testcontainers resources + rules.add(declaredClassPattern("org\\.testcontainers\\..*")); + + // any docker-java API's resources + rules.add(declaredClassPattern("com\\.github\\.dockerjava\\..*")); + + rules.add(isSomeServer()); + + rules.add(isLeftoverExecutorService()); + + this.rules = rules.build(); + } + + private static boolean isEnabled() + { + if (System.getProperty("ManageTestResources.enabled") != null) { + return Boolean.getBoolean("ManageTestResources.enabled"); + } + if (System.getenv("DISABLE_REPORT_RESOURCE_HUNGRY_TESTS_CHECK") != null) { + return false; + } + return true; + } + + @Override + public void onStart(ITestContext context) + { + try { + if (!enabled) { + log.debug("ManageTestResources.onStart ignored, check is disabled"); + return; + } + + log.info("ManageTestResources.onStart: running checks"); + manageResources(context, BEFORE_CLASS); + } + catch (ReflectiveOperationException | Error e) { + reportListenerFailure( + ManageTestResources.class, + "Failed to process %s: \n%s", + context, + getStackTraceAsString(e)); + } + } + + @Override + public void onTestStart(ITestResult result) {} + + @Override + public void onTestSuccess(ITestResult result) {} + + @Override + public void onTestFailure(ITestResult result) {} + + @Override + public void onTestSkipped(ITestResult result) {} + + @Override + public void onTestFailedButWithinSuccessPercentage(ITestResult result) {} + + @Override + public void onFinish(ITestContext context) + { + try { + if (!enabled) { + log.debug("ManageTestResources.onFinish ignored, check is disabled"); + return; + } + + log.info("ManageTestResources.onFinish: running checks"); + manageResources(context, AFTER_CLASS); + } + catch (ReflectiveOperationException | Error e) { + reportListenerFailure( + ManageTestResources.class, + "Failed to process %s: \n%s", + context, + getStackTraceAsString(e)); + } + } + + private void manageResources(ITestContext context, Stage stage) + throws ReflectiveOperationException + { + Set testClasses = Stream.of(context.getAllTestMethods()) + .map(ITestNGMethod::getTestClass) + .collect(toImmutableSet()); + for (ITestClass testClass : testClasses) { + manageResources(testClass, stage); + } + } + + private void manageResources(ITestClass testClass, Stage stage) + throws ReflectiveOperationException + { + // This method should not be called when check not enabled. + checkState(enabled, "Not enabled"); + + for (Object instance : testClass.getInstances(false)) { + for (Class clazz = instance.getClass(); clazz != null; clazz = clazz.getSuperclass()) { + for (Field field : clazz.getDeclaredFields()) { + if (field.isAnnotationPresent(Suppress.class)) { + log.debug("Skipping audit of field due to field-level suppression %s: %s", field.getAnnotation(Suppress.class), field); + continue; + } + + field.setAccessible(true); + Object value = field.get(instance); + if (value == null) { + continue; + } + if (value.getClass().isAnnotationPresent(Suppress.class)) { + log.debug( + "Skipping audit of field due to suppression %s on the field actual type (%s): %s", + value.getClass().getAnnotation(Suppress.class), + value.getClass(), + field); + continue; + } + for (Rule rule : rules) { + if (rule.isExpensiveResource(field, value, stage)) { + reportListenerFailure( + ManageTestResources.class, + """ + + \tTest instance field has value that looks like a resource + \t Test class: %s + \t Instance: %s + \t Field: %s + \t Value: %s + \t Test execution stage: %s + \t Matching rule: %s + + \tResources must not be allocated in a field initializer or a test constructor, + \tand must be freed when test class is completed. + \tDepending which rule has been violated, if the reported class holds on + \tto resources only conditionally, you can add @ResourcePresence to declare that. + """, + testClass.getRealClass(), + instance, + field, + value, + stage, + rule); + } + } + } + } + } + } + + enum Stage + { + BEFORE_CLASS, + AFTER_CLASS, + } + + @FunctionalInterface + private interface Rule + { + boolean isExpensiveResource(Field field, Object value, Stage stage); + } + + private static Rule declaredClassPattern(@Language("RegExp") String classNamePattern) + { + Pattern pattern = Pattern.compile(classNamePattern); + return named( + "declaredClassPattern(%s)".formatted(classNamePattern), + (field, value, stage) -> pattern.matcher(field.getType().getName()).matches()); + } + + /** + * Report {@link AutoCloseable} instances. + */ + private static Rule isAutoCloseable() + { + return named("isAutoCloseable", (field, value, stage) -> { + if (!(value instanceof AutoCloseable)) { + return false; + } + + // Disallow AutoCloseable instances, even if not started, before class is run. + // Allocation of such resources generally correlates with too eager initialization. + // Allow stopped instances after class to work nicely with + // `AbstractTestQueryFramework.closeAfterClass` usages. + return !(stage == AFTER_CLASS && isResourceStopped(value)); + }); + } + + /** + * Report anything that looks like a "Server" and does not appear to be stopped after class is finished. + */ + private static Rule isSomeServer() + { + return named("isSomeServer", (field, value, stage) -> { + Class type = field.getType(); + if (!type.getName().endsWith("Server")) { + return false; + } + + // Disallow "*Server" instances, even if not started, before class is run. + // Allow stopped instances to work nicely with `AbstractTestQueryFramework.closeAfterClass` usages. + return !(stage == AFTER_CLASS && isResourceStopped(value)); + }); + } + + // see https://github.com/trinodb/trino/commit/9e3b45b743e1cc350e759c1bed3cfb336b1cf610 + private static Optional isInstanceTransactionManagerField() + { + return tryLoadClass("io.trino.transaction.TransactionManager").map(transactionManagerClass -> + named( + "is-instance-TransactionManager-field", + (field, value, stage) -> { + // Exclude static fields to allow usages of the form: `static final TransactionManager TRANSACTION_MANAGER = createTestTransactionManager()` + if (isStatic(field.getModifiers())) { + return false; + } + return transactionManagerClass.isInstance(value); + })); + } + + private static boolean isResourceStopped(Object resource) + { + return Stream.of(resource.getClass().getMethods()) + .filter(method -> method.isAnnotationPresent(ResourcePresence.class)) + .collect(toOptional()) + .map(resourcePresence -> { + try { + return !(boolean) resourcePresence.invoke(resource); + } + catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + }) + .orElse(false); // assume not stopped + } + + /** + * Report {@link java.util.concurrent.ExecutorService} instances that are left behind. + * Does not report prematurely initialized instances since typical execuctor service creates + * threads lazily. + */ + private static Rule isLeftoverExecutorService() + { + return named("isLeftoverExecutorService", (field, value, stage) -> { + if (!(value instanceof ExecutorService executorService)) { + return false; + } + + // TODO we should check for executorService.isTerminated(), i.e. require tests to wait for completion of any background tasks + return stage == AFTER_CLASS && !executorService.isShutdown(); + }); + } + + private static Rule named(String name, Rule delegate) + { + return new Rule() + { + @Override + public boolean isExpensiveResource(Field field, Object value, Stage stage) + { + return delegate.isExpensiveResource(field, value, stage); + } + + @Override + public String toString() + { + return name; + } + }; + } + + private static Optional> tryLoadClass(String className) + { + try { + return Optional.of(Thread.currentThread().getContextClassLoader().loadClass(className)); + } + catch (ClassNotFoundException e) { + return Optional.empty(); + } + } + + /** + * Suppresses checks when + *
    + *
  • field is annotated + *
  • field actual type is annotated (note that the annotation *IS* inherited) + *
+ */ + @Retention(RUNTIME) + @Target({TYPE, FIELD}) + @Inherited + public @interface Suppress + { + String because(); + } +} diff --git a/testing/trino-testing-services/src/main/java/io/trino/testng/services/ProgressLoggingListener.java b/testing/trino-testing-services/src/main/java/io/trino/testng/services/ProgressLoggingListener.java index 08b7123ccd596..8ad1e94176fd6 100644 --- a/testing/trino-testing-services/src/main/java/io/trino/testng/services/ProgressLoggingListener.java +++ b/testing/trino-testing-services/src/main/java/io/trino/testng/services/ProgressLoggingListener.java @@ -16,6 +16,8 @@ import com.google.common.base.Joiner; import io.airlift.log.Logger; import org.testng.IClassListener; +import org.testng.IInvokedMethod; +import org.testng.IInvokedMethodListener; import org.testng.ITestClass; import org.testng.ITestContext; import org.testng.ITestListener; @@ -27,7 +29,7 @@ import static java.lang.String.format; public class ProgressLoggingListener - implements IClassListener, ITestListener + implements IClassListener, ITestListener, IInvokedMethodListener { private static final Logger LOGGER = Logger.get(ProgressLoggingListener.class); private final boolean enabled; @@ -53,19 +55,33 @@ private static boolean isEnabled() } @Override - public void onStart(ITestContext context) - { - } + public void onStart(ITestContext context) {} @Override - public void onTestStart(ITestResult testCase) + public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { if (!enabled) { return; } - LOGGER.info("[TEST START] %s", formatTestName(testCase)); + boolean testMethod = method.isTestMethod(); + boolean configurationMethod = method.isConfigurationMethod(); + if (testMethod) { + LOGGER.info("[TEST START] %s", formatTestName(testResult)); + } + if (configurationMethod) { + LOGGER.info("[CONFIGURATION] %s for %s", method, formatTestName(testResult)); + } + if (!testMethod && !configurationMethod) { + LOGGER.info("[UNKNOWN THING] %s for %s", method, formatTestName(testResult)); + } } + @Override + public void afterInvocation(IInvokedMethod method, ITestResult testResult) {} + + @Override + public void onTestStart(ITestResult testCase) {} + @Override public void onTestSuccess(ITestResult testCase) { @@ -99,14 +115,10 @@ public void onTestSkipped(ITestResult testCase) } @Override - public void onTestFailedButWithinSuccessPercentage(ITestResult testCase) - { - } + public void onTestFailedButWithinSuccessPercentage(ITestResult testCase) {} @Override - public void onFinish(ITestContext context) - { - } + public void onFinish(ITestContext context) {} @Override public void onBeforeClass(ITestClass testClass) diff --git a/testing/trino-testing-services/src/main/resources/META-INF/services/org.testng.ITestNGListener b/testing/trino-testing-services/src/main/resources/META-INF/services/org.testng.ITestNGListener index b1a3ced6b3ff8..2120fcb3fe894 100644 --- a/testing/trino-testing-services/src/main/resources/META-INF/services/org.testng.ITestNGListener +++ b/testing/trino-testing-services/src/main/resources/META-INF/services/org.testng.ITestNGListener @@ -1,3 +1,4 @@ +io.trino.testng.services.ManageTestResources io.trino.testng.services.ReportOrphanedExecutors io.trino.testng.services.ReportPrivateMethods io.trino.testng.services.ReportUnannotatedMethods diff --git a/testing/trino-testing/src/main/java/io/trino/testing/AbstractTestQueryFramework.java b/testing/trino-testing/src/main/java/io/trino/testing/AbstractTestQueryFramework.java index a894f0c52680e..a06d5ff82f0f0 100644 --- a/testing/trino-testing/src/main/java/io/trino/testing/AbstractTestQueryFramework.java +++ b/testing/trino-testing/src/main/java/io/trino/testing/AbstractTestQueryFramework.java @@ -89,15 +89,16 @@ public abstract class AbstractTestQueryFramework { private static final SqlParser SQL_PARSER = new SqlParser(); + private AutoCloseableCloser afterClassCloser; private QueryRunner queryRunner; private H2QueryRunner h2QueryRunner; - private final AutoCloseableCloser afterClassCloser = AutoCloseableCloser.create(); private io.trino.sql.query.QueryAssertions queryAssertions; @BeforeClass public void init() throws Exception { + afterClassCloser = AutoCloseableCloser.create(); queryRunner = afterClassCloser.register(createQueryRunner()); h2QueryRunner = afterClassCloser.register(new H2QueryRunner()); queryAssertions = new io.trino.sql.query.QueryAssertions(queryRunner); @@ -110,12 +111,13 @@ protected abstract QueryRunner createQueryRunner() public final void close() throws Exception { - try (afterClassCloser) { + try (AutoCloseable ignored = afterClassCloser) { checkQueryMemoryReleased(); checkQueryInfosFinal(); checkTasksDone(); } finally { + afterClassCloser = null; queryRunner = null; h2QueryRunner = null; queryAssertions = null; @@ -678,6 +680,11 @@ private T inTransaction(Session session, Function transactionSes @CanIgnoreReturnValue protected final T closeAfterClass(T resource) { + checkState( + afterClassCloser != null, + "closeAfterClass invoked before test is initialized or after it is torn down. " + + "In particular, make sure you do not allocate any resources in a test class constructor, " + + "as this can easily lead to OutOfMemoryErrors and other types of test flakiness."); return afterClassCloser.register(resource); } } diff --git a/testing/trino-testing/src/main/java/io/trino/testing/DistributedQueryRunner.java b/testing/trino-testing/src/main/java/io/trino/testing/DistributedQueryRunner.java index 812e677ad6cec..7eb1aeff56adb 100644 --- a/testing/trino-testing/src/main/java/io/trino/testing/DistributedQueryRunner.java +++ b/testing/trino-testing/src/main/java/io/trino/testing/DistributedQueryRunner.java @@ -86,20 +86,22 @@ public class DistributedQueryRunner private static final Logger log = Logger.get(DistributedQueryRunner.class); private static final String ENVIRONMENT = "testing"; - private final TestingDiscoveryServer discoveryServer; - private final TestingTrinoServer coordinator; - private final Optional backupCoordinator; - private final Runnable registerNewWorker; + private TestingDiscoveryServer discoveryServer; + private TestingTrinoServer coordinator; + private Optional backupCoordinator; + private Runnable registerNewWorker; private final List servers = new CopyOnWriteArrayList<>(); private final List functionBundles = new CopyOnWriteArrayList<>(ImmutableList.of(AbstractTestQueries.CUSTOM_FUNCTIONS)); private final List plugins = new CopyOnWriteArrayList<>(); private final Closer closer = Closer.create(); - private final TestingTrinoClient trinoClient; + private TestingTrinoClient trinoClient; private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private boolean closed; + public static Builder builder(Session defaultSession) { return new Builder<>(defaultSession); @@ -566,6 +568,9 @@ public void loadExchangeManager(String name, Map properties) @Override public final void close() { + if (closed) { + return; + } cancelAllQueries(); try { closer.close(); @@ -573,6 +578,17 @@ public final void close() catch (IOException e) { throw new UncheckedIOException(e); } + discoveryServer = null; + coordinator = null; + backupCoordinator = Optional.empty(); + registerNewWorker = () -> { + throw new IllegalStateException("Already closed"); + }; + servers.clear(); + functionBundles.clear(); + plugins.clear(); + trinoClient = null; + closed = true; } private void cancelAllQueries() diff --git a/testing/trino-testing/src/test/java/io/trino/testing/TestTestingTrinoClient.java b/testing/trino-testing/src/test/java/io/trino/testing/TestTestingTrinoClient.java index 144f6a5899dec..326e519b3e9f3 100644 --- a/testing/trino-testing/src/test/java/io/trino/testing/TestTestingTrinoClient.java +++ b/testing/trino-testing/src/test/java/io/trino/testing/TestTestingTrinoClient.java @@ -83,6 +83,7 @@ public void teardown() throws Exception { server.close(); + server = null; } @Test diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestDenyOnSchema.java b/testing/trino-tests/src/test/java/io/trino/execution/TestDenyOnSchema.java index c705bc69d2bee..8f972c4e8341e 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestDenyOnSchema.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestDenyOnSchema.java @@ -102,6 +102,7 @@ public void teardown() { assertions.close(); assertions = null; + queryRunner = null; // closed by assertions.close } @Test(dataProvider = "privileges") diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestDenyOnTable.java b/testing/trino-tests/src/test/java/io/trino/execution/TestDenyOnTable.java index 770d6517f68f3..ecadc95a1f15b 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestDenyOnTable.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestDenyOnTable.java @@ -99,6 +99,7 @@ public void teardown() { assertions.close(); assertions = null; + queryRunner = null; // closed by assertions.close } @Test(dataProvider = "privileges") diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestDeprecatedFunctionWarning.java b/testing/trino-tests/src/test/java/io/trino/execution/TestDeprecatedFunctionWarning.java index ceb0072be74bd..f1e3116c0e610 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestDeprecatedFunctionWarning.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestDeprecatedFunctionWarning.java @@ -77,6 +77,7 @@ public void setUp() public void tearDown() { queryRunner.close(); + queryRunner = null; } @Test diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestGrantOnSchema.java b/testing/trino-tests/src/test/java/io/trino/execution/TestGrantOnSchema.java index decf1166b13e4..d551aa0903fc3 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestGrantOnSchema.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestGrantOnSchema.java @@ -68,6 +68,7 @@ public void teardown() { assertions.close(); assertions = null; + queryRunner = null; // closed by assertions.close } @Test(dataProviderClass = DataProviders.class, dataProvider = "trueFalse") diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestGrantOnTable.java b/testing/trino-tests/src/test/java/io/trino/execution/TestGrantOnTable.java index 52838f408fd1b..b4bc745dfc828 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestGrantOnTable.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestGrantOnTable.java @@ -75,6 +75,7 @@ public void teardown() { assertions.close(); assertions = null; + queryRunner = null; // closed by assertions.close } @Test(dataProviderClass = DataProviders.class, dataProvider = "trueFalse") diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestPendingStageState.java b/testing/trino-tests/src/test/java/io/trino/execution/TestPendingStageState.java index e1b08e8326b4e..97b0545cd5014 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestPendingStageState.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestPendingStageState.java @@ -72,6 +72,7 @@ public void tearDown() { if (queryRunner != null) { queryRunner.close(); + queryRunner = null; } } } diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestQueryTracker.java b/testing/trino-tests/src/test/java/io/trino/execution/TestQueryTracker.java index 8b7ad6324afbf..e4b3f6d8562a1 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestQueryTracker.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestQueryTracker.java @@ -41,7 +41,7 @@ public class TestQueryTracker private final CountDownLatch freeze = new CountDownLatch(1); private final CountDownLatch interrupted = new CountDownLatch(1); - @AfterClass + @AfterClass(alwaysRun = true) public void unfreeze() { freeze.countDown(); diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestRevokeOnSchema.java b/testing/trino-tests/src/test/java/io/trino/execution/TestRevokeOnSchema.java index 159c10505c9ec..2ab6172d5fcc7 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestRevokeOnSchema.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestRevokeOnSchema.java @@ -70,6 +70,7 @@ public void teardown() { assertions.close(); assertions = null; + queryRunner = null; // closed by assertions.close } @Test(dataProvider = "privilegesAndUsers") diff --git a/testing/trino-tests/src/test/java/io/trino/execution/TestRevokeOnTable.java b/testing/trino-tests/src/test/java/io/trino/execution/TestRevokeOnTable.java index 397e1abbf9069..404c0867aa6cc 100644 --- a/testing/trino-tests/src/test/java/io/trino/execution/TestRevokeOnTable.java +++ b/testing/trino-tests/src/test/java/io/trino/execution/TestRevokeOnTable.java @@ -84,6 +84,7 @@ public void teardown() { assertions.close(); assertions = null; + queryRunner = null; // closed by assertions.close } @Test(dataProvider = "privilegesAndUsers") diff --git a/testing/trino-tests/src/test/java/io/trino/sql/planner/BaseIcebergCostBasedPlanTest.java b/testing/trino-tests/src/test/java/io/trino/sql/planner/BaseIcebergCostBasedPlanTest.java index aea1b99d4a72f..7790b93634729 100644 --- a/testing/trino-tests/src/test/java/io/trino/sql/planner/BaseIcebergCostBasedPlanTest.java +++ b/testing/trino-tests/src/test/java/io/trino/sql/planner/BaseIcebergCostBasedPlanTest.java @@ -34,6 +34,7 @@ import io.trino.spi.connector.ConnectorFactory; import io.trino.testing.containers.Minio; import io.trino.testing.minio.MinioClient; +import io.trino.testng.services.ManageTestResources; import org.apache.hadoop.hive.metastore.TableType; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterSuite; @@ -79,6 +80,7 @@ public abstract class BaseIcebergCostBasedPlanTest // The container needs to be shared, since bucket name cannot be reused between tests. // The bucket name is used as a key in TrinoFileSystemCache which is managed in static manner. @GuardedBy("sharedMinioLock") + @ManageTestResources.Suppress(because = "This resource is leaked, but consciously -- there is no known way to avoid that") private static Minio sharedMinio; private static final Object sharedMinioLock = new Object(); diff --git a/testing/trino-tests/src/test/java/io/trino/tests/TestGetTableStatisticsOperations.java b/testing/trino-tests/src/test/java/io/trino/tests/TestGetTableStatisticsOperations.java index 52f75e0430118..07ebf26296768 100644 --- a/testing/trino-tests/src/test/java/io/trino/tests/TestGetTableStatisticsOperations.java +++ b/testing/trino-tests/src/test/java/io/trino/tests/TestGetTableStatisticsOperations.java @@ -23,6 +23,7 @@ import io.trino.testing.LocalQueryRunner; import io.trino.testing.QueryRunner; import org.intellij.lang.annotations.Language; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -52,6 +53,14 @@ protected QueryRunner createQueryRunner() return localQueryRunner; } + @AfterClass(alwaysRun = true) + public void tearDown() + { + localQueryRunner.close(); + localQueryRunner = null; + metadata = null; + } + @BeforeMethod public void resetCounters() { diff --git a/testing/trino-tests/src/test/java/io/trino/tests/TestServer.java b/testing/trino-tests/src/test/java/io/trino/tests/TestServer.java index c9f03e3a4f768..561c18e474bbe 100644 --- a/testing/trino-tests/src/test/java/io/trino/tests/TestServer.java +++ b/testing/trino-tests/src/test/java/io/trino/tests/TestServer.java @@ -106,6 +106,8 @@ public void tearDown() throws Exception { closeAll(server, client); + server = null; + client = null; } @Test