/**
 * Copyright (C) 2009-2014 FoundationDB, LLC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.foundationdb.server.test.it.isolation;

import com.foundationdb.server.error.ErrorCode;
import com.foundationdb.sql.embedded.JDBCConnection;

import java.sql.*;
import java.util.Properties;

import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class ReadCommittedIsolationDT extends IsolationITBase
{
    private static final int NROWS = 10000;

    @Before
    public void populate() throws SQLException {
        createTable(SCHEMA_NAME, "t1", "id INT PRIMARY KEY, n INT");
        Properties props = new Properties();
        props.put("user", SCHEMA_NAME);
        props.put("constraintCheckTime", "DELAYED_WITH_RANGE_CACHE_ALWAYS_UNTIL_COMMIT");
        try (Connection conn = DriverManager.getConnection(CONNECTION_URL, props);
             PreparedStatement stmt = conn.prepareStatement("INSERT INTO t1 VALUES(?,?)")) {
            conn.setAutoCommit(false);
            for (int i = 0; i < NROWS; i++) {
                stmt.setInt(1, i);
                stmt.setInt(2, i);
                stmt.executeUpdate();
            }
            conn.commit();
        }
    }

    protected void slowScan() throws SQLException {
        int sum = 0;
        try (Connection conn = getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM t1")) {
            while (rs.next()) {
                sum += rs.getInt(2);
                try {
                    Thread.sleep(6);
                }
                catch (InterruptedException ex) {
                    break;
                }
            }
        }
        assertEquals((NROWS * (NROWS - 1)) / 2, sum);
    }

    protected void manyScans() throws SQLException {
        int sum = 0;
        try (Connection conn = getConnection();
             PreparedStatement stmt = conn.prepareStatement("SELECT n FROM t1 WHERE id = ?")) {
            for (int i = 0; i < NROWS; i++) {
                stmt.setInt(1, i);
                try (ResultSet rs = stmt.executeQuery()) {
                    if (rs.next()) {
                        sum += rs.getInt(1);
                    }
                }
                try {
                    Thread.sleep(6);
                }
                catch (InterruptedException ex) {
                    break;
                }
            }
        }
        assertEquals((NROWS * (NROWS - 1)) / 2, sum);
    }

    @Test
    @Isolation(Connection.TRANSACTION_SERIALIZABLE)
    @SQLExceptionExpected(errorCode = ErrorCode.FDB_PAST_VERSION)
    public void slowScanPastVersion() throws SQLException {
        slowScan();
    }

    @Test
    @Isolation(JDBCConnection.TRANSACTION_READ_COMMITTED_NO_SNAPSHOT)
    public void slowScanReadCommitted() throws SQLException {
        slowScan();
    }

    @Test
    @Isolation(Connection.TRANSACTION_SERIALIZABLE)
    @SQLExceptionExpected(errorCode = ErrorCode.FDB_PAST_VERSION)
    public void manyScansPastVersion() throws SQLException {
        manyScans();
    }

    @Test
    @Isolation(JDBCConnection.TRANSACTION_READ_COMMITTED_NO_SNAPSHOT)
    public void manyScansReadCommitted() throws SQLException {
        manyScans();
    }

}

Add DT to check long-running scans / transactions.