/*
 * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2010, 2019 SAP. All rights reserved.
 * Copyright (c) 2019 IBM Corporation. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     SAP    - tests rewritten
package org.eclipse.persistence.testing.tests.jpa.advanced;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import jakarta.persistence.EntityManager;
import jakarta.persistence.LockModeType;
import jakarta.persistence.PessimisticLockScope;
import jakarta.persistence.Query;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.advanced.Address;
import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator;
import org.eclipse.persistence.testing.models.jpa.advanced.Dealer;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.Equipment;
import org.eclipse.persistence.testing.models.jpa.advanced.EquipmentCode;
import org.eclipse.persistence.testing.models.jpa.advanced.LargeProject;
import org.eclipse.persistence.testing.models.jpa.advanced.SmallProject;
import org.eclipse.persistence.testing.models.jpa.advanced.entities.EntyA;
import org.eclipse.persistence.testing.models.jpa.advanced.entities.EntyB;
import org.eclipse.persistence.testing.models.jpa.advanced.entities.EntyC;
import org.eclipse.persistence.testing.models.jpa.advanced.entities.EntyD;
import org.eclipse.persistence.testing.models.jpa.advanced.entities.EntyE;

/**
 * <p>
 * <b>Purpose</b>: Test Pessimistic Locking Extended Scope functionality.
 * <p>
 * <b>Description</b>: Test the relationship will be locked or unlocked under different situations
 * <p>
 */
 public class PessimisticLockingExtendedScopeTestSuite extends JUnitTestCase {

    public PessimisticLockingExtendedScopeTestSuite() {
        super();
    }

    public PessimisticLockingExtendedScopeTestSuite(String name) {
        super(name);
    }

    public static Test suite() {
        TestSuite suite = new TestSuite("PessimisticLocking ExtendedScope TestSuite");
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testSetup"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES1"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES2"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES3"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES4"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES5"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES6"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES7"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES8"));
        suite.addTest(new PessimisticLockingExtendedScopeTestSuite("testPESSMISTIC_ES9"));
        return suite;
    }

    public void testSetup() {
        ServerSession session = JUnitTestCase.getServerSession();
        new AdvancedTableCreator().replaceTables(session);
        //make the entity EquipmentCode read-write for the following tests
        ClassDescriptor descriptor = session.getDescriptor(EquipmentCode.class);
        boolean shouldBeReadOnly = descriptor.shouldBeReadOnly();
        descriptor.setShouldBeReadOnly(false);
        clearCache();
    }

    interface Actor<X> {
        void setup(EntityManager em);

        X getEntityToLock(EntityManager em);

        void modify(EntityManager em);

        void check(EntityManager em, X lockedEntity);
    }

    // Entity relationships for which the locked entity contains the foreign key
    // will be locked with bidirectional one-to-one mapping without mappedBy
    // (Scenario 1.1)
    public void testPESSMISTIC_ES1() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        final EntyA a = new EntyA();

        final Actor actor = new Actor<EntyA>() {

            @Override
            public void setup(EntityManager em) {
                EntyC c = new EntyC();
                em.persist(c);
                a.setName("test");
                a.setEntyC(c);
                em.persist(a);
            }

            @Override
            public EntyA getEntityToLock(EntityManager em) {
                return em.find(EntyA.class, a.getId());
            }

            @Override
            public void modify(EntityManager em) {
                EntyA a2 = em.find(EntyA.class, a.getId());
                a2.setEntyC(null);
            }

            @Override
            public void check(EntityManager em, EntyA lockedEntity) {
                em.refresh(lockedEntity);
                assertNotNull("other transaction modified row concurrently", lockedEntity.getEntyC());
            }

        };

        testNonrepeatableRead(actor);
    }

    // Entity relationships for which the locked entity contains the foreign key
    // will be locked with unidirectional one-to-one mapping(Scenario 1.2)
    public void testPESSMISTIC_ES2() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        final EntyA a = new EntyA();

        final Actor actor = new Actor<EntyA>() {

            @Override
            public void setup(EntityManager em) {
                EntyB b = new EntyB();
                a.setEntyB(b);
                em.persist(a);
            }

            @Override
            public EntyA getEntityToLock(EntityManager em1) {
                return em1.find(EntyA.class, a.getId());
            }

            @Override
            public void modify(EntityManager em2) {
                EntyA a2 = em2.find(EntyA.class, a.getId());
                a2.setEntyB(null);
            }

            @Override
            public void check(EntityManager em1, EntyA lockedEntity) {
                em1.refresh(lockedEntity);
                assertNotNull("other transaction modified row concurrently", lockedEntity.getEntyB());
            }

        };

        testNonrepeatableRead(actor);
    }


    // Entity relationships for which the locked entity contains the foreign key
    // will be locked with unidirectional many-to-one mapping(Scenario 1.3)
    public void testPESSMISTIC_ES3() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        final Equipment eq = new Equipment();

        final Actor actor = new Actor<Equipment>() {

            @Override
            public void setup(EntityManager em) {
                EquipmentCode eqCode = new EquipmentCode();
                eqCode.setCode("A");
                em.persist(eqCode);
                eq.setEquipmentCode(eqCode);
                em.persist(eq);
            }

            @Override
            public Equipment getEntityToLock(EntityManager em1) {
                return em1.find(Equipment.class, eq.getId());
            }

            @Override
            public void modify(EntityManager em2) {
                Equipment eq2 = em2.find(Equipment.class, eq.getId());
                eq2.setEquipmentCode(null);
            }

            @Override
            public void check(EntityManager em1, Equipment lockedEntity) {
                em1.refresh(lockedEntity);
                assertNotNull("other transaction modified row concurrently", lockedEntity.getEquipmentCode());
            }

        };

        testNonrepeatableRead(actor);
    }


    // Entity relationships for which the locked entity contains the foreign key
    // will be locked with bidirectional many-to-one mapping(Scenario 1.4)
    public void testPESSMISTIC_ES4() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        if ((JUnitTestCase.getServerSession()).getPlatform().isHANA()) {
            // HANA currently doesn't support pessimistic locking with queries on multiple tables
            // feature is under development (see bug 384129), but test should be skipped for the time being
            return;
        }
        final Employee emp = new Employee();

        final Actor actor = new Actor<Employee>() {

            @Override
            public void setup(EntityManager em) {
                Address ads = new Address("SomeStreet", "somecity", "province", "country", "postalcode");
                emp.setAddress(ads);
                em.persist(emp);
            }

            @Override
            public Employee getEntityToLock(EntityManager em1) {
                return em1.find(Employee.class, emp.getId());
            }

            @Override
            public void modify(EntityManager em2) {
                Employee emp2 = em2.find(Employee.class, emp.getId());
                emp2.setAddress((Address)null);
            }

            @Override
            public void check(EntityManager em1, Employee lockedEntity) {
                em1.refresh(lockedEntity);
                assertNotNull("other transaction modified row concurrently", lockedEntity.getAddress());
            }

        };

        testNonrepeatableRead(actor);
    }


    // Relationships owned by the entity that are contained in join tables will
    // be locked with Unidirectional OneToMany mapping (Scenario 2.2)
    public void testPESSMISTIC_ES5() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        final EntyA entyA = new EntyA();

        final Actor actor = new Actor<EntyA>() {

            @Override
            public void setup(EntityManager em) {
                em.persist(entyA);
                entyA.getEntyDs().add(new EntyD());
            }

            @Override
            public EntyA getEntityToLock(EntityManager em1) {
                return em1.find(EntyA.class, entyA.getId());
            }

            @Override
            public void modify(EntityManager em2) {
                EntyA entyA2 = em2.find(EntyA.class, entyA.getId());
                entyA2.setEntyDs(null);
            }

            @Override
            public void check(EntityManager em1, EntyA lockedEntity) {
                em1.refresh(lockedEntity);
                assertNotNull("other transaction modified row concurrently", lockedEntity.getEntyDs());

                final Collection collection;
                if (getServerSession().getPlatform().isMaxDB()) {
                    // avoid accessing EntyD's table as this would lead to a dead lock
                    Query query = em1.createNativeQuery("SELECT t2.entyDs_ID FROM ADV_ENTYA_ADV_ENTYD t2, ADV_ENTYA t1 WHERE ((? = t1.ID) AND ((t2.EntyA_ID = t1.ID)))");
                    query.setParameter(1, lockedEntity.getId());
                    collection = query.getResultList();
                } else {
                    collection = lockedEntity.getEntyDs();
                }

                assertFalse("other transaction modified row concurrently", collection.isEmpty());
            }

        };

        testNonrepeatableRead(actor);
    }


    //Relationships owned by the entity that are contained in join tables will be locked with Unidirectional ManyToMany mapping (Scenario 2.3)
    public void testPESSMISTIC_ES6() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        final EntyA entyA = new EntyA();

        final Actor actor = new Actor<EntyA>() {

            @Override
            public void setup(EntityManager em) {
                Collection entyEs = new ArrayList();
                EntyE entyE1 = new EntyE();
                EntyE entyE2 = new EntyE();
                entyEs.add(entyE1);
                entyEs.add(entyE2);
                entyA.setEntyEs(entyEs);
                em.persist(entyA);
            }

            @Override
            public EntyA getEntityToLock(EntityManager em1) {
                return em1.find(EntyA.class, entyA.getId());
            }

            @Override
            public void modify(EntityManager em2) {
                EntyA entyA2 = em2.find(EntyA.class, entyA.getId());
                entyA2.setEntyEs(null);
            }

            @Override
            public void check(EntityManager em1, EntyA lockedEntity) {
                em1.refresh(lockedEntity);
                assertNotNull("other transaction modified row concurrently", lockedEntity.getEntyEs());
                assertFalse("other transaction modified row concurrently", lockedEntity.getEntyEs().isEmpty());
            }

        };

        testNonrepeatableRead(actor);
    }



    /*
     * The test should assert that the following phenomenon does not occur
     * after a row has been locked by T1:
     *
     * - P2 (Non-repeatable read): Transaction T1 reads a row. Another
     * transaction T2 then modifies or deletes that row, before T1 has
     * committed or rolled back.
     */
    private <X> void testNonrepeatableRead(final Actor<X> actor) throws InterruptedException {
        // Cannot create parallel entity managers in the server.
        if (isOnServer() || !isSelectForUpateSupported()) {
            return;
        }

        EntityManager em = createEntityManager();
        EntyC c = null;
        try {
            beginTransaction(em);
            actor.setup(em);
            commitTransaction(em);
        } catch (RuntimeException ex) {
            throw ex;
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }

        Exception lockTimeOutException = null;
        LockModeType lockMode = LockModeType.PESSIMISTIC_WRITE;
        Map<String, Object> properties = new HashMap();
        properties.put(QueryHints.PESSIMISTIC_LOCK_SCOPE, PessimisticLockScope.EXTENDED);
        properties.put(QueryHints.PESSIMISTIC_LOCK_TIMEOUT, 10000);

        EntityManager em1 = createEntityManager();
        try {
            beginTransaction(em1);
            X locked = actor.getEntityToLock(em1);
            em1.lock(locked, lockMode, properties);

            final EntityManager em2 = createEntityManager();
            try {
                // P2 (Non-repeatable read)
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        try {
                            beginTransaction(em2);
                            actor.modify(em2);
                            commitTransaction(em2); // might wait for lock to be released
                        } catch (jakarta.persistence.RollbackException ex) {
                            if (ex.getMessage().indexOf("org.eclipse.persistence.exceptions.DatabaseException") == -1) {
                                ex.printStackTrace();
                                fail("it's not the right exception");
                            }
                        }
                    }
                };

                Thread t2 = new Thread(runnable);
                t2.start();
                Thread.sleep(1000);       // allow t2 to atempt update
                actor.check(em1, locked); // assert repeatable read
                rollbackTransaction(em1); // release lock
                t2.join();                // wait until t2 finished
            } finally {
                if (isTransactionActive(em2)) {
                    rollbackTransaction(em2);
                }
                closeEntityManager(em2);
            }
        } finally {
            if (isTransactionActive(em1)) {
                rollbackTransaction(em1);
            }
            closeEntityManager(em1);
        }
    }



    //Bidirectional OneToOne Relationship with target entity has foreign key, entity does not contain the foreign key will not be locked (Scenario 3.1)
    public void testPESSMISTIC_ES7() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        // Cannot create parallel entity managers in the server.
        if (! isOnServer() && isSelectForUpateSupported()) {
            EntityManager em = createEntityManager();
            EntyA a = null;
            EntyC c = null;
            try{
                beginTransaction(em);
                a = new EntyA();
                c = new EntyC();
                em.persist(c);
                a.setEntyC(c);
                em.persist(a);
                commitTransaction(em);
            }catch (RuntimeException ex){
                throw ex;
            }finally{
                if (isTransactionActive(em)){
                    rollbackTransaction(em);
                }
                closeEntityManager(em);
            }

            Exception lockTimeOutException = null;
            LockModeType lockMode = LockModeType.PESSIMISTIC_WRITE;
            Map<String, Object> properties = new HashMap();
            properties.put(QueryHints.PESSIMISTIC_LOCK_SCOPE, PessimisticLockScope.NORMAL);
            EntityManager em1= createEntityManager();

            try{
                beginTransaction(em1);
                c = em1.find(EntyC.class, c.getId());
                em1.lock(c, lockMode, properties);
                EntityManager em2 = createEntityManager();
                try{
                    beginTransaction(em2);
                    c = em2.find(EntyC.class, c.getId());
                    c.setEntyA(null);
                    commitTransaction(em2);
                } catch(jakarta.persistence.RollbackException ex){
                    fail("it should not throw the exception!!!");
                }finally{
                    if (isTransactionActive(em2)){
                        rollbackTransaction(em2);
                    }
                    closeEntityManager(em2);
                }
            }catch (Exception ex){
                throw ex;
            }finally{
                if (isTransactionActive(em1)){
                    rollbackTransaction(em1);
                }
                closeEntityManager(em1);
            }
        }
    }

    //Unidirectional OneToMany Relationship, in which entity does not contain the foreign key will not be locked (Scenario 3.2)
    public void testPESSMISTIC_ES8() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        if ((JUnitTestCase.getServerSession()).getPlatform().isHANA()) {
            // HANA currently doesn't support pessimistic locking with queries on multiple tables
            // feature is under development (see bug 384129), but test should be skipped for the time being
            return;
        }
        // Cannot create parallel entity managers in the server.
        if (! isOnServer() && isSelectForUpateSupported()) {
            EntityManager em = createEntityManager();
            Employee emp = null;
            try{
                beginTransaction(em);
                emp = new Employee();
                emp.getDealers().add(new Dealer("Honda", "Kanata"));
                em.persist(emp);
                commitTransaction(em);
            }catch (RuntimeException ex){
                throw ex;
            }finally{
                if (isTransactionActive(em)){
                    rollbackTransaction(em);
                }
                closeEntityManager(em);
            }

            Exception lockTimeOutException = null;
            LockModeType lockMode = LockModeType.PESSIMISTIC_WRITE;
            Map<String, Object> properties = new HashMap();
            properties.put(QueryHints.PESSIMISTIC_LOCK_SCOPE, PessimisticLockScope.NORMAL);
            EntityManager em1= createEntityManager();

            try {
                beginTransaction(em1);
                emp = em1.find(Employee.class, emp.getId());
                em1.lock(emp, lockMode, properties);
                EntityManager em2 = createEntityManager();
                try {
                    beginTransaction(em2);
                    emp = em1.find(Employee.class, emp.getId());
                    emp.setDealers(null);
                    commitTransaction(em2);
                } catch (jakarta.persistence.RollbackException ex){
                    fail("it should not throw the exception!!!");
                } finally {
                    if (isTransactionActive(em2)) {
                        rollbackTransaction(em2);
                    }
                    closeEntityManager(em2);
                }
            } catch (Exception ex){
                fail("it should not throw the exception!!!");
                throw ex;
            } finally {
                if (isTransactionActive(em1)){
                    rollbackTransaction(em1);
                }
                closeEntityManager(em1);
            }
        }
    }

    //Bidirectional ManyToMany Relationship, in which entity does not contain the foreign key will not be locked by default (Scenario 3.3)
    public void testPESSMISTIC_ES9() throws Exception {
        if (getPlatform().isSQLServer()) {
            warning("This test deadlocks on SQL Server");
            return;
        }
        if ((JUnitTestCase.getServerSession()).getPlatform().isHANA()) {
            // HANA currently doesn't support pessimistic locking with queries on multiple tables
            // feature is under development (see bug 384129), but test should be skipped for the time being
            return;
        }
        // Cannot create parallel entity managers in the server.
        if (! isOnServer() && isSelectForUpateSupported()) {
            EntityManager em = createEntityManager();
            Employee emp = null;
            try{
                beginTransaction(em);
                emp = new Employee();
                SmallProject smallProject = new SmallProject();
                smallProject.setName("New High School Set Up");
                emp.addProject(smallProject);
                LargeProject largeProject = new LargeProject();
                largeProject.setName("Downtown Light Rail");
                largeProject.setBudget(5000);
                emp.addProject(largeProject);
                em.persist(emp);
                commitTransaction(em);
            }catch (RuntimeException ex){
                throw ex;
            }finally{
                if (isTransactionActive(em)){
                    rollbackTransaction(em);
                }
                closeEntityManager(em);
            }

            Exception lockTimeOutException = null;
            LockModeType lockMode = LockModeType.PESSIMISTIC_WRITE;
            Map<String, Object> properties = new HashMap();
            properties.put(QueryHints.PESSIMISTIC_LOCK_SCOPE, PessimisticLockScope.NORMAL);
            EntityManager em1= createEntityManager();

            try{
                beginTransaction(em1);
                emp = em1.find(Employee.class, emp.getId());
                em1.lock(emp, lockMode, properties);
                EntityManager em2 = createEntityManager();
                try{
                    beginTransaction(em2);
                    emp = em1.find(Employee.class, emp.getId());
                    emp.setProjects(null);
                    commitTransaction(em2);
                }catch(jakarta.persistence.RollbackException ex){
                    fail("it should not throw the exception!!!");
                }finally{
                    if (isTransactionActive(em2)){
                        rollbackTransaction(em2);
                    }
                    closeEntityManager(em2);
                }
            }catch (Exception ex){
                fail("it should not throw the exception!!!");
                throw ex;
            }finally{
                if (isTransactionActive(em1)){
                    rollbackTransaction(em1);
                }
                closeEntityManager(em1);
            }
        }
    }
}
