/**
 * END USER LICENSE AGREEMENT (“EULA”)
 *
 * READ THIS AGREEMENT CAREFULLY (date: 9/13/2011):
 * http://www.akiban.com/licensing/20110913
 *
 * BY INSTALLING OR USING ALL OR ANY PORTION OF THE SOFTWARE, YOU ARE ACCEPTING
 * ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. YOU AGREE THAT THIS
 * AGREEMENT IS ENFORCEABLE LIKE ANY WRITTEN AGREEMENT SIGNED BY YOU.
 *
 * IF YOU HAVE PAID A LICENSE FEE FOR USE OF THE SOFTWARE AND DO NOT AGREE TO
 * THESE TERMS, YOU MAY RETURN THE SOFTWARE FOR A FULL REFUND PROVIDED YOU (A) DO
 * NOT USE THE SOFTWARE AND (B) RETURN THE SOFTWARE WITHIN THIRTY (30) DAYS OF
 * YOUR INITIAL PURCHASE.
 *
 * IF YOU WISH TO USE THE SOFTWARE AS AN EMPLOYEE, CONTRACTOR, OR AGENT OF A
 * CORPORATION, PARTNERSHIP OR SIMILAR ENTITY, THEN YOU MUST BE AUTHORIZED TO SIGN
 * FOR AND BIND THE ENTITY IN ORDER TO ACCEPT THE TERMS OF THIS AGREEMENT. THE
 * LICENSES GRANTED UNDER THIS AGREEMENT ARE EXPRESSLY CONDITIONED UPON ACCEPTANCE
 * BY SUCH AUTHORIZED PERSONNEL.
 *
 * IF YOU HAVE ENTERED INTO A SEPARATE WRITTEN LICENSE AGREEMENT WITH AKIBAN FOR
 * USE OF THE SOFTWARE, THE TERMS AND CONDITIONS OF SUCH OTHER AGREEMENT SHALL
 * PREVAIL OVER ANY CONFLICTING TERMS OR CONDITIONS IN THIS AGREEMENT.
 */

package com.akiban.sql.pg;

import com.akiban.server.error.ErrorCode;

import org.junit.Before;
import org.junit.Test;
import static junit.framework.Assert.*;

import java.sql.SQLException;
import java.sql.Statement;

public class JMXCancelationIT extends PostgresServerITBase
{
    private static final int SERVER_JMX_PORT = 8082;
    private static final String SERVER_ADDRESS = "localhost";
    private static final int N = 1000;

    @Before
    public void loadDB() throws Exception {
        Statement statement = connection.createStatement();
        statement.execute("CREATE TABLE t(id INTEGER NOT NULL PRIMARY KEY)");
        for (int id = 0; id < N; id++) {
            statement.execute(String.format("INSERT INTO t VALUES(%s)", id));
        }
        statement.close();
    }

    @Test
    public void testCancel() throws Exception {
        test("cancelQuery", false);
        test("killConnection", true);
    }

    private void test(String method, boolean closedOK) throws Exception {
        Thread queryThread = startQueryThread(closedOK);
        Thread.sleep(250);
        JMXInterpreter jmx = null;
        try {
            jmx = new JMXInterpreter(false);
            Integer[] sessions = (Integer[])
                jmx.makeBeanCall(SERVER_ADDRESS, SERVER_JMX_PORT,
                                 "com.akiban:type=PostgresServer",
                                 "CurrentSessions", null, "get");
            assertEquals(1, sessions.length);
            jmx.makeBeanCall(SERVER_ADDRESS, SERVER_JMX_PORT,
                             "com.akiban:type=PostgresServer",
                             method, sessions, "method");
            queryThread.join();
        }
        finally {
            if (jmx != null) {
                jmx.close();
            }
        }
    }

    private Thread startQueryThread(final boolean closedOK) throws Exception {
        Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    Statement statement = null;
                    try {
                        statement = connection.createStatement();
                        statement.execute("SELECT COUNT(*) FROM t t1, t t2, t t3");
                        fail("Query should not complete.");
                    }
                    catch (SQLException ex) {
                        String sqlState = ex.getSQLState();
                        // Kill case can see either cancel or connection close.
                        if (!closedOK || !"08006".equals(sqlState))
                            assertEquals(ErrorCode.QUERY_CANCELED.getFormattedValue(), sqlState);
                    }
                    catch (Exception ex) {
                        fail(ex.toString());
                    }
                    finally {
                        try {
                            if (statement != null)
                                statement.close();
                        }
                        catch (SQLException ex) {
                        }
                    }
                }
            });
        thread.setDaemon(false);
        thread.start();
        return thread;
    }

}

@@ -1387,16 +1387,44 @@
 ert.*;%0A%0A
+import java.sql.Connection;%0A
 import j
@@ -1473,16 +1473,93 @@
 ement;%0A%0A
+import java.util.ArrayList;%0Aimport java.util.Arrays;%0Aimport java.util.List;%0A%0A
 public c
@@ -2209,32 +2209,105 @@
 Query%22, false);%0A
+    %7D%0A%0A    @Test%0A    public void testKillConnection() throws Exception %7B%0A
         test(%22ki
@@ -2413,92 +2413,8 @@
 n %7B%0A
-        Thread queryThread = startQueryThread(closedOK);%0A        Thread.sleep(250);%0A
     
@@ -2495,32 +2495,33 @@
 rpreter(false);%0A
+%0A
             Inte
@@ -2764,42 +2764,620 @@
     
-assertEquals(1, sessions.length
+List%3CInteger%3E before = Arrays.asList(sessions);%0A%0A            Thread queryThread = startQueryThread(closedOK);%0A            Thread.sleep(250);%0A%0A            sessions = (Integer%5B%5D)%0A                jmx.makeBeanCall(SERVER_ADDRESS, SERVER_JMX_PORT,%0A                                 %22com.akiban:type=PostgresServer%22,%0A                                 %22CurrentSessions%22, null, %22get%22);%0A            List%3CInteger%3E after = Arrays.asList(sessions);%0A            after = new ArrayList%3CInteger%3E(after);%0A            after.removeAll(before);%0A%0A            assertEquals(1, after.size());%0A            Integer session = after.get(0
 );%0A
+%0A
     
@@ -3533,24 +3533,39 @@
  method,
+ new Object%5B%5D %7B
  session
 s, %22meth
@@ -3556,17 +3556,18 @@
  session
-s
+ %7D
 , %22metho
@@ -3567,24 +3567,25 @@
  %22method%22);%0A
+%0A
             
@@ -3912,24 +3912,74 @@
 oid run() %7B%0A
+                    Connection connection = null;%0A
             
@@ -4032,32 +4032,87 @@
           try %7B%0A
+                        connection = openConnection();%0A
                 
@@ -4965,32 +4965,89 @@
 tement.close();%0A
+                            closeConnection(connection);%0A
                 
@@ -5079,35 +5079,32 @@
          catch (
-SQL
 Exception ex) %7B%0A

Make JMX cancelation test robust in the face of left-over connections.