/*******************************************************************************
 * Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/  
package org.eclipse.persistence.testing.tests.flashback;

import java.util.*;
import java.math.*;
import org.eclipse.persistence.testing.models.employee.domain.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.history.*;
import org.eclipse.persistence.internal.history.*;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.platform.database.OraclePlatform;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.mappings.querykeys.*;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.testing.framework.*;

/**
 * <b>Purpose:</b> Tests all those unique scenarios involving
 * Flashback that can not easily be generalized into a few
 * generic cases.
 */
public class FlashbackUnitTestSuite extends TestSuite {
    public FlashbackUnitTestSuite() {
        setDescription("Fast unit testing of the flashback feature.");
    }

    protected Object getSystemChangeNumber() {
        return ((FlashbackTestModel)getContainer()).getSystemChangeNumber();
    }

    protected Object getTimestamp() {
        return FlashbackTestModel.getTimestamp();
    }

    protected AsOfClause getAsOfClause() {
        return ((FlashbackTestModel)getContainer()).getAsOfClause();
    }

    public void _testAsOfStringLiteralTest() {
        if (getSession().getProject().hasGenericHistorySupport()) {
            return;
        }
        ValueReadQuery scnQuery = ((OraclePlatform)getSession().getPlatform()).getSystemChangeNumberQuery();
        long sCNNow = ((BigDecimal)getSession().executeQuery(scnQuery)).longValue();
        long testSCN = ((Number)getAsOfClause().getValue()).longValue();
        ExpressionBuilder builder = new ExpressionBuilder(Employee.class);
        AsOfClause sCNClause = new AsOfSCNClause(builder.value("" + sCNNow + " - " + (sCNNow - testSCN)));

        ReadAllQuery query = new ReadAllQuery(Employee.class);
        query.setAsOfClause(sCNClause);
        query.dontMaintainCache();
        Vector result = (Vector)getSession().executeQuery(query);
        if (result.size() != 12) {
            throw new TestErrorException("Expected 12 objects, read " + result.size());
        }
    }

    public void _testAsOfParameterTest() {
        ReadAllQuery query = new ReadAllQuery(Employee.class);
        query.dontMaintainCache();
        query.addArgument("ASOFCLAUSE");

        Vector arguments = new Vector();
        Object value = getAsOfClause().getValue();
        arguments.add(value);

        Expression parameterExp = query.getExpressionBuilder().getParameter("ASOFCLAUSE");
        if (getAsOfClause().isAsOfSCNClause()) {
            query.setAsOfClause(new AsOfSCNClause(parameterExp));
        } else {
            query.setAsOfClause(new AsOfClause(parameterExp));
        }

        Vector result = (Vector)getSession().executeQuery(query, arguments);
        if (result.size() != 12) {
            throw new TestErrorException("Expected 12 objects, read " + result.size());
        }

        /*arguments.set(0, new java.sql.Timestamp(System.currentTimeMillis()));
        result = (Vector)getSession().executeQuery(query, arguments);
        if (result.size() != 0) {
            throw new TestErrorException("Expected 0 objects, read " + result.size());
        }*/
    }

    public void _testAsOfCurrentTimeMillisTest() {
        if (getSession().getProject().hasGenericHistorySupport()) {
            return;
        }
        // Must get the current time from the database as a future or too long pass time will trigger an error.
        long value = ((Date)getSession().executeQuery(new ValueReadQuery("Select SYSDATE from DUAL"))).getTime();
        AsOfClause clause = new AsOfClause(value);
        ReadAllQuery query = new ReadAllQuery(Employee.class);
        query.dontMaintainCache();
        query.setAsOfClause(clause);

        Vector employees = (Vector)getSession().executeQuery(query);

        // Since the current time gets mapped to the SCN +/- 5 minutes,
        // the query of the current time may, or may contain employees,
        // so cannot verify the result, just make sure the query worked.
    }

    public void _testAsOfCurrentTimeMillisParameterTest() {
        if (getSession().getProject().hasGenericHistorySupport()) {
            return;
        }

        // Must get the current time from the database as a future or too long pass time will trigger an error.
        long value = ((Date)getSession().executeQuery(new ValueReadQuery("Select SYSDATE from DUAL"))).getTime();
        AsOfClause clause = new AsOfClause((new ExpressionBuilder()).getParameter("TIME"));
        ReadAllQuery query = new ReadAllQuery(Employee.class);
        query.dontMaintainCache();
        query.setAsOfClause(clause);
        query.addArgument("TIME");
        Vector arguments = new Vector();
        arguments.add(new Long(value));

        Vector employees = (Vector)getSession().executeQuery(query, arguments);
        if (employees.size() != 0) {
            throw new TestErrorException("Somehow the long value was not converted to a proper timestamp.  Check the SQL against: " + value);
        }
    }

    public void _testAsOfExpressionMathTest() {
        if (!getAsOfClause().isAsOfSCNClause()) {
            return;
        }
        ValueReadQuery scnQuery = ((OraclePlatform)getSession().getPlatform()).getSystemChangeNumberQuery();
        long sCNNow = ((BigDecimal)getSession().executeQuery(scnQuery)).longValue();
        long testSCN = ((BigDecimal)getAsOfClause().getValue()).longValue();
        ExpressionBuilder builder = new ExpressionBuilder();
        Expression expression = ExpressionMath.subtract(builder.value(sCNNow), builder.value(sCNNow - testSCN));

        ReadAllQuery query = new ReadAllQuery(Employee.class);
        query.setAsOfClause(new AsOfSCNClause(expression));
        query.dontMaintainCache();
        Vector result = (Vector)getSession().executeQuery(query);
        if (result.size() != 12) {
            throw new TestErrorException("Expected 12 objects, read " + result.size());
        }
    }

    /**
     * A query result can be cached normally if the builder is not as of
     * a past time.  However, if this condition is true but a a joined attribute
     * as of a past time is added, what will happen?
     * <p>What should happen is either an exception should be thrown, or the
     * joined attribute should be read as of the current time.  This test will find out
     * which.
     */
    public void _testCacheCorruptedByJoinedAttributeTest() {
        // Try reading all projects now connected to all projects as of a past time.
        try {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();

            ExpressionBuilder project = new ExpressionBuilder(LargeProject.class);
            ExpressionBuilder oldProject = new ExpressionBuilder(LargeProject.class);
            oldProject.asOf(getAsOfClause());
            Expression criteria = project.equal(oldProject).and(oldProject.get("teamLeader").notNull());
            ReadAllQuery query = new ReadAllQuery(LargeProject.class, criteria);
            query.addJoinedAttribute(oldProject.get("teamLeader"));
            Vector projects = (Vector)getSession().executeQuery(query);
            for (int i = 0; i < projects.size(); i++) {
                LargeProject next = (LargeProject)projects.get(i);
                if (next.getTeamLeader() != null) {
                    throw new TestErrorException("The dynamic query must still return objects as they exist now, even if a joined attribute is added as of a past time.");
                }
            }
        } finally {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();
        }
    }

    /**
     * Tests corruption from joined attributes again.
     * This test is simpler and more lethal than the previous one, for it cuts to
     * the core of the problem.  To tell if past rows are being returned, we can
     * not just look at the builder.
     */
    public void _testCacheCorruptedByJoinedAttribute2Test() {
        // Try reading all projects now connected to all projects as of a past time.
        try {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();

            ExpressionBuilder project = new ExpressionBuilder(LargeProject.class);
            Expression criteria = project.get("teamLeader").asOf(getAsOfClause()).notNull();
            ReadAllQuery query = new ReadAllQuery(LargeProject.class, criteria);
            query.addJoinedAttribute("teamLeader");
            Vector projects = (Vector)getSession().executeQuery(query);
            for (int i = 0; i < projects.size(); i++) {
                LargeProject next = (LargeProject)projects.get(i);
                if (next.getTeamLeader() != null) {
                    throw new TestErrorException("The dynamic query must still return objects as they exist now, even if a joined attribute is added on an attribute read as of a past time.");
                }
            }
        } finally {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();
        }
    }

    /**
     * Tests corruption from joined attributes again.
     * This test is simpler and more lethal than the previous one, for it cuts to
     * the core of the problem.  To tell if past rows are being returned, we can
     * not just look at the builder.
     */
    public void _testCacheCorruptedByBatchAttributeTest() {
        // Try reading all projects now connected to all projects as of a past time.
        try {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();

            ExpressionBuilder project = new ExpressionBuilder(LargeProject.class);
            Expression criteria = project.get("teamLeader").asOf(getAsOfClause()).notNull();
            ReadAllQuery query = new ReadAllQuery(LargeProject.class, criteria);
            query.addBatchReadAttribute("teamLeader");
            Vector projects = (Vector)getSession().executeQuery(query);
            for (int i = 0; i < projects.size(); i++) {
                LargeProject next = (LargeProject)projects.get(i);
                if (next.getTeamLeader() != null) {
                    throw new TestErrorException("The dynamic query must still return objects as they exist now, even if a batched attribute is added on an attribute read as of a past time.");
                }
            }
        } finally {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();
        }
    }

    /**
     * This is testing for a condition that should never happen.
     */
    public void _testCacheIsolationTest() {
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
        Session hs = getSession().acquireHistoricalSession(getAsOfClause());
        try {
            hs.readAllObjects(Employee.class);
            Vector employees = ((AbstractSession)getSession()).getIdentityMapAccessorInstance().getAllFromIdentityMap(null, Employee.class, null);
            if ((employees != null) && (employees.size() > 0)) {
                throw new TestErrorException("" + employees.size() + " objects read in a HistoricalSession were cached in the global session.");
            }
        } finally {
            hs.release();
        }
    }

    /**
     * This is testing for a condition that should never happen.
     */
    public void _testCacheIsolationAcrossRelationshipsTest() {
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
        Session hs = getSession().acquireHistoricalSession(getAsOfClause());
        try {
            Vector pastEmployees = hs.readAllObjects(Employee.class);
            for (int i = 0; i < pastEmployees.size(); i++) {
                Employee employee = (Employee)pastEmployees.get(i);
                employee.getProjects();
                employee.getAddress();
                employee.getPhoneNumbers();
            }
            Vector projects = ((AbstractSession)getSession()).getIdentityMapAccessorInstance().getAllFromIdentityMap(null, Project.class, null);
            Vector addresses = ((AbstractSession)getSession()).getIdentityMapAccessorInstance().getAllFromIdentityMap(null, Address.class, null);
            Vector phoneNumbers = ((AbstractSession)getSession()).getIdentityMapAccessorInstance().getAllFromIdentityMap(null, PhoneNumber.class, null);

            if ((projects.size() > 0) || (addresses.size() > 0) || (phoneNumbers.size() > 0)) {
                throw new TestErrorException("" + projects.size() + " projects, " + addresses.size() + " addresses, and " + phoneNumbers.size() + " phone numbers read in a HistoricalSession were cached in the global session.");
            }
        } finally {
            hs.release();
        }
    }

    public void _testCannotExecuteWriteInHistoricalSessionExceptionTest() {
        Session hs = getSession().acquireHistoricalSession(getAsOfClause());
        try {
            ((org.eclipse.persistence.internal.sessions.AbstractSession)hs).writeObject(new Employee());
            throw new TestErrorException("Exception not thrown in executing a write in a TimeAwareSession.");
        } catch (ValidationException ve) {
            if (ve.getErrorCode() != QueryException.INVALID_QUERY_ON_HISTORICAL_SESSION) {
                throw new TestErrorException("Wrong exception thrown.", ve);
            }
        } catch (TestErrorException tee) {
            throw tee;
        } catch (Exception e) {
            throw new TestErrorException("Exception not thrown in executing a write in a Historical session.  Instead triggered: ", e);
        } finally {
            hs.release();
        }
    }

    public void _testDynamicQueryUsingParallelExpressionTest() {
        // Try reading all projects now connected to all projects as of a past time.
        try {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();

            ExpressionBuilder project = new ExpressionBuilder(LargeProject.class);
            ExpressionBuilder oldProject = new ExpressionBuilder(LargeProject.class);
            oldProject.asOf(getAsOfClause());
            Expression criteria = project.equal(oldProject).and(oldProject.get("teamLeader").notNull());
            Vector projects = getSession().readAllObjects(LargeProject.class, criteria);
            if (projects.size() != 3) {
                throw new TestErrorException("Expected to read 6 projects, instead read: " + projects.size());
            }
            for (int i = 0; i < projects.size(); i++) {
                LargeProject next = (LargeProject)projects.get(i);
                if (next.getTeamLeader() != null) {
                    throw new TestErrorException("The dynamic query must still return objects as they exist now.");
                }
            }
        } finally {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();
        }
    }

    public void _testDynamicQueryUsingQueryKeyTest() {
        // Try reading all projects now connected to all projects as of a past time.
        try {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();
            ExpressionBuilder builder = new ExpressionBuilder(LargeProject.class);
            Expression joinCriteria = builder.getField("PROJECT.PROJ_ID").equal(builder.getParameter("PROJECT.PROJ_ID"));
            OneToOneQueryKey self = new OneToOneQueryKey();
            self.setName("this");
            self.setJoinCriteria(joinCriteria);
            self.setReferenceClass(LargeProject.class);
            getSession().getDescriptor(LargeProject.class).addQueryKey(self);

            ExpressionBuilder project = new ExpressionBuilder(LargeProject.class);
            Expression oldProject = project.get("this");
            oldProject.asOf(getAsOfClause());
            Expression criteria = oldProject.get("teamLeader").notNull();
            Vector projects = getSession().readAllObjects(LargeProject.class, criteria);
            if (projects.size() != 3) {
                throw new TestErrorException("Expected to read 6 projects, instead read: " + projects.size());
            }
            for (int i = 0; i < projects.size(); i++) {
                LargeProject next = (LargeProject)projects.get(i);
                if (next.getTeamLeader() != null) {
                    throw new TestErrorException("The dynamic query must still return objects as they exist now.");
                }
            }
        } finally {
            getSession().getIdentityMapAccessor().initializeIdentityMaps();
        }
    }

    public void _testNoNestedHistoricalSessionsAllowedExceptionTest() {
        Session hs = getSession().acquireHistoricalSession(getAsOfClause());
        try {
            Session nhs = hs.acquireHistoricalSession(getAsOfClause());
            nhs.release();
            throw new TestErrorException("Exception not thrown in acquiring a nested HistoricalSession.");
        } catch (ValidationException ve) {
            if (ve.getErrorCode() != ValidationException.CANNOT_ACQUIRE_HISTORICAL_SESSION) {
                throw new TestErrorException("Wrong exception thrown.", ve);
            }
        } catch (TestErrorException tee) {
            throw tee;
        } catch (Exception e) {
            throw new TestErrorException("Exception not thrown in reading past versions of objects into the global cache.  Instead triggered: ", e);
        } finally {
            hs.release();
        }
    }

    public void _testNoTransactionsInHistoricalSessionExceptionTest() {
        HistoricalSession hs = (HistoricalSession)getSession().acquireHistoricalSession(getAsOfClause());
        try {
            hs.beginTransaction();
            hs.rollbackTransaction();
            throw new TestErrorException("Exception not thrown in beginning a transaction.");
        } catch (ValidationException ve1) {
            if (ve1.getErrorCode() != ValidationException.OPERATION_NOT_SUPPORTED) {
                throw new TestErrorException("Wrong exception thrown.", ve1);
            } else {
                try {
                    hs.commitTransaction();
                } catch (ValidationException ve2) {
                    if (ve2.getErrorCode() != ValidationException.OPERATION_NOT_SUPPORTED) {
                        throw new TestErrorException("Wrong exception thrown.", ve2);
                    } else {
                        try {
                            hs.rollbackTransaction();
                        } catch (ValidationException ve3) {
                            if (ve3.getErrorCode() != ValidationException.OPERATION_NOT_SUPPORTED) {
                                throw new TestErrorException("Wrong exception thrown.", ve3);
                            } else {
                                try {
                                    hs.acquireUnitOfWork();
                                } catch (ValidationException ve4) {
                                    if (ve4.getErrorCode() != ValidationException.OPERATION_NOT_SUPPORTED) {
                                        throw new TestErrorException("Wrong exception thrown.", ve4);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (TestErrorException tee) {
            throw tee;
        } catch (Exception e) {
            throw new TestErrorException("Exception not thrown in reading past versions of objects into the global cache.  Instead triggered: ", e);
        } finally {
            hs.release();
        }
    }

    public void _testParameterBindingTest() {
        ExpressionBuilder builder = new ExpressionBuilder();
        Expression expression = builder.get("firstName").equal(builder.getParameter("FIRSTNAME"));
        Vector arguments = new Vector();
        arguments.add("Bob");

        ReadObjectQuery query = new ReadObjectQuery(Employee.class);
        query.setAsOfClause(getAsOfClause());
        query.dontMaintainCache();
        query.addArgument("FIRSTNAME");
        Employee result = (Employee)getSession().executeQuery(query, arguments);
        if (!result.getFirstName().equals("Bob")) {
            throw new TestErrorException("Expected Bob, read " + result);
        }
        arguments.set(0, "Sarah");
        result = (Employee)getSession().executeQuery(query, arguments);
        if (!result.getFirstName().equals("Sarah")) {
            throw new TestErrorException("Expected Sarah, read " + result);
        }
    }

    /**
     * Tests the entire point of a TimeAwareSession, which is to allow
     * caching of read results, which in turn guarantees that circular references
     * form a circle, not an infinite loop.
     */
    public void _testSuccessfulCachingTest() {
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
        Session hs = getSession().acquireHistoricalSession(getAsOfClause());
        try {
            Employee pastManager = (Employee)hs.readObject(Employee.class, new ExpressionBuilder().anyOf("managedEmployees").get("id").greaterThan(0));
            Vector employees = pastManager.getManagedEmployees();
            for (int i = 0; i < employees.size(); i++) {
                Employee employee = (Employee)employees.get(i);
                if (employee.getManager() != pastManager) {
                    throw new TestErrorException("Objects read in a HistoricalSession are not being cached properly by identity.");
                }
            }
        } finally {
            hs.release();
        }
    }

    public void _testOuterJoinTest() {
        internalOuterJoinTest(true);
    }

    public void _testOuterJoinTestWithoutAsOf() {
        internalOuterJoinTest(false);
    }

    void internalOuterJoinTest(boolean withAsOf) {
        ReadAllQuery query = new ReadAllQuery(LargeProject.class);
        ExpressionBuilder builder = query.getExpressionBuilder();
        Expression expression = builder.getAllowingNull("teamLeader").get("firstName").equal("Sarah");
        expression = expression.or(builder.get("name").equal("TOPEmployee Management"));
        query.setSelectionCriteria(expression);
        query.dontMaintainCache();
        if(withAsOf) {
            query.setAsOfClause(getAsOfClause());
        }
        Vector result = (Vector)getSession().executeQuery(query);
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
        int expectedSize = (withAsOf ? 2 : 1);
        if ((result == null) || (result.size() != expectedSize)) {
            throw new TestErrorException("Expected "+expectedSize+" objects, read " + result.size());
        }
    }

    public void _testHistoricalQueriesMustPreserveGlobalCacheExceptionTest() {
        ReadAllQuery query = new ReadAllQuery(Employee.class);
        query.setSelectionCriteria(query.getExpressionBuilder().get("firstName").equal("Bob"));
        query.setAsOfClause(new AsOfSCNClause(new Long(0)));
        try {
            getSession().executeQuery(query);
            getSession().getIdentityMapAccessor().initializeIdentityMaps();
            throw new TestErrorException("Exception not thrown in reading past versions of objects into the global cache.");
        } catch (QueryException qe) {
            if (qe.getErrorCode() != QueryException.HISTORICAL_QUERIES_MUST_PRESERVE_GLOBAL_CACHE) {
                throw new TestErrorException("Wrong exception thrown.", qe);
            }
        } catch (TestErrorException tee) {
            throw tee;
        } catch (Exception e) {
            throw new TestErrorException("Exception not thrown in reading past versions of objects into the global cache.  Instead triggered: ", e);
        }
    }

    public void _testHistoricalQueriesOnlySupportedOnOracleExceptionTest() {
        boolean genericHistory = getSession().getProject().hasGenericHistorySupport();
        ReadAllQuery query = new ReadAllQuery(Employee.class);
        query.setSelectionCriteria(query.getExpressionBuilder().get("firstName").equal("Bob"));
        query.setAsOfClause(getAsOfClause());
        query.dontMaintainCache();
        DatabaseLogin oldLogin = getSession().getLogin();
        DatabaseLogin newLogin = (DatabaseLogin)oldLogin.clone();
        newLogin.useAccess();
        try {
            getAbstractSession().setLogin(newLogin);
            getSession().executeQuery(query);
            getSession().getIdentityMapAccessor().initializeIdentityMaps();
            if (!genericHistory) {
                throw new TestErrorException("Exception not thrown in reading past versions of objects outside of Oracle.");
            }
        } catch (QueryException qe) {
            if (qe.getErrorCode() != QueryException.HISTORICAL_QUERIES_ONLY_SUPPORTED_ON_ORACLE) {
                throw new TestErrorException("Wrong exception thrown.", qe);
            }
        } catch (TestErrorException tee) {
            throw tee;
        } catch (Exception e) {
            throw new TestErrorException("Exception not thrown in reading past versions of objects outside of Oracle.  Instead triggered: " + e.toString(), e);
        } finally {
            getAbstractSession().setLogin(oldLogin);
        }
    }

    public void _testHistoricalSessionOnlySupportedOnOracleExceptionTest() {
        if (getSession().getProject().hasGenericHistorySupport()) {
            return;
        }
        DatabaseLogin oldLogin = getSession().getLogin();
        DatabaseLogin newLogin = (DatabaseLogin)oldLogin.clone();
        newLogin.useAccess();
        try {
            getAbstractSession().setLogin(newLogin);
            Session hs = getSession().acquireHistoricalSession(getAsOfClause());
            hs.release();
            throw new TestErrorException("Exception not thrown in acquiring a HistoricalSession outside of Oracle.");
        } catch (ValidationException ve) {
            if (ve.getErrorCode() != ValidationException.HISTORICAL_SESSION_ONLY_SUPPORTED_ON_ORACLE) {
                throw new TestErrorException("Wrong exception thrown.", ve);
            }
        } catch (TestErrorException tee) {
            throw tee;
        } catch (Exception e) {
            throw new TestErrorException("Exception not thrown in reading past versions of objects into the global cache.  Instead triggered: ", e);
        } finally {
            getAbstractSession().setLogin(oldLogin);
        }
    }

    public void addTests() {
        addTest(new UnitTestCase("AsOfCurrentTimeMillisTest"));
        // broken addTest(new UnitTestCase("AsOfCurrentTimeMillisParameterTest"));
        addTest(new UnitTestCase("AsOfExpressionMathTest"));
        addTest(new UnitTestCase("AsOfParameterTest"));
        addTest(new UnitTestCase("AsOfStringLiteralTest"));
        // broken addTest(new UnitTestCase("CacheCorruptedByJoinedAttributeTest"));
        //broken addTest(new UnitTestCase("CacheCorruptedByJoinedAttribute2Test"));
        addTest(new UnitTestCase("CacheCorruptedByBatchAttributeTest"));
        addTest(new UnitTestCase("CacheIsolationTest"));
        addTest(new UnitTestCase("CacheIsolationAcrossRelationshipsTest"));
        addTest(new UnitTestCase("CannotExecuteWriteInHistoricalSessionExceptionTest"));
        addTest(new UnitTestCase("DynamicQueryUsingQueryKeyTest"));
        addTest(new UnitTestCase("DynamicQueryUsingParallelExpressionTest"));
        addTest(new UnitTestCase("NoNestedHistoricalSessionsAllowedExceptionTest"));
        addTest(new UnitTestCase("NoTransactionsInHistoricalSessionExceptionTest"));
        addTest(new UnitTestCase("SuccessfulCachingTest"));
        addTest(new UnitTestCase("OuterJoinTest"));
        addTest(new UnitTestCase("OuterJoinTestWithoutAsOf"));
        addTest(new UnitTestCase("HistoricalQueriesMustPreserveGlobalCacheExceptionTest"));
        addTest(new UnitTestCase("HistoricalQueriesOnlySupportedOnOracleExceptionTest"));
        addTest(new UnitTestCase("HistoricalSessionOnlySupportedOnOracleExceptionTest"));
    }
}
