/*
 * 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
 *
 */
 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);
            }
        }
    }
}
