/* * Copyright (c) 2010, PostgreSQL Global Development Group * See the LICENSE file in the project root for more information. */ package org.postgresql.test.jdbc4.jdbc41; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.postgresql.test.TestUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; public class AbortTest { private static final int SLEEP_SECONDS = 30; private static final int SLEEP_MILLISECONDS = SLEEP_SECONDS * 1000; private Connection _conn; @Before public void setUp() throws Exception { _conn = TestUtil.openDB(); } @After public void tearDown() throws SQLException { TestUtil.closeDB(_conn); } @Test public void testAbort() throws SQLException, InterruptedException, ExecutionException { final ExecutorService executor = Executors.newFixedThreadPool(2); long startTime = System.currentTimeMillis(); Future<SQLException> workerFuture = executor.submit(new Callable<SQLException>() { public SQLException call() { try { Statement stmt = _conn.createStatement(); stmt.execute("SELECT pg_sleep(" + SLEEP_SECONDS + ")"); } catch (SQLException e) { return e; } return null; } }); Future<SQLException> abortFuture = executor.submit(new Callable<SQLException>() { public SQLException call() { ExecutorService abortExecutor = Executors.newSingleThreadExecutor(); try { _conn.abort(abortExecutor); } catch (SQLException e) { return e; } abortExecutor.shutdown(); try { abortExecutor.awaitTermination(SLEEP_SECONDS, TimeUnit.SECONDS); } catch (InterruptedException e) { } return null; } }); SQLException workerException = workerFuture.get(); long endTime = System.currentTimeMillis(); SQLException abortException = abortFuture.get(); if (abortException != null) { throw abortException; } if (workerException == null) { fail("Statement execution should have been aborted, thus throwing an exception"); } // suppose that if it took at least 95% of sleep time, aborting has failed and we've waited the // full time assertTrue(endTime - startTime < SLEEP_MILLISECONDS * 95 / 100); assertTrue(_conn.isClosed()); } /** * According to the javadoc, calling abort on a closed connection is a no-op. */ @Test public void testAbortOnClosedConnection() throws SQLException { _conn.close(); try { _conn.abort(Executors.newSingleThreadExecutor()); } catch (SQLException e) { fail(e.getMessage()); } } }