/*
 * Copyright (c) 1998, 2021 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 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
package org.eclipse.persistence.testing.tests.unitofwork;

import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.framework.WriteObjectTest;


/**
 * <p>
 * <b>Purpose</b>: This test checks if UOW merge is perfromed properly.
 * <p>
 * <b>Motivation </b>: This test was written to fix a bug. While in a unit of work, a new
 * object that refrenced clones, after the merge still refrenced clones.
 * <p>
 * <b>Design</b>: implement an equals method for objects that always returns true, and in another object
 * implement an equals that always returns false. Now check the four paths mentioned below by
 * registering the two objects into the UOW, compare the clones returned. If the two objects are
 * different (regardless of what they think) then different clones must be returned.
 *
 * <p>
 * <b>Responsibilities</b>: Verify that the registration of the objects does not depend on the equals method
 * <p>
 * <b>Features Used</b>: Unit Of Work, Registering feature
 * <p>
 * <b>Paths Covered</b>: Within the unit of work, different parts of the employee were set with clones:
 * <ul>
 * <li> <i>Think they are equal but are unequal, clones are different</i>
 * <li> <i>Think they are equal and are equal, clones are identical</i>
 * <li> <i>Think they are unequal but are equal, clones are identical</i>
 * <li> <i>Think they are unequal and are unequal, clones are different</i>
 * </ul>
 */
public class RegisterationUnitOfWorkTest extends WriteObjectTest {
    public Object unitOfWorkWorkingCopy;
    public UnitOfWork unitOfWork;

    /**
     * RegisterationUnitOfWorkTests constructor comment.
     */
    public RegisterationUnitOfWorkTest() {
        super();
    }

    /**
     * RegisterationUnitOfWorkTests constructor comment.
     */
    public RegisterationUnitOfWorkTest(Object originalObject) {
        super(originalObject);
        setDescription("The test registers equal and unequal objects to the database and sees if the" +
                       "' registeration works properly by checking if different clones are returned for similar objects");
    }

    @Override
    public void setup() {
        super.setup();
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
        this.unitOfWork = getSession().acquireUnitOfWork();
    }

    @Override
    protected void test() {
        testRegisteringEqualObjects();
        testRegisteringUnequalObjects();
        this.unitOfWork.commit();
    }

    protected void testRegisteringEqualObjects() {
        /* This test will try to register two equal objects
        In the first case the two objects are equal and the method returns true
        In the second case the two objects are equal and the equals method returns false
        We should get exactly the same clone when we register both */
        Person person = Person.example1();
        Person personClone1 = (Person)this.unitOfWork.registerObject(person);
        Person personClone2 = (Person)this.unitOfWork.registerObject(person);
        if (!(personClone1 == personClone2)) {
            throw new TestErrorException("Registration fault: Clones are different for equal objects");
        }
        MailAddress address = MailAddress.example1();
        MailAddress addressClone1 = (MailAddress)this.unitOfWork.registerObject(address);
        MailAddress addressClone2 = (MailAddress)this.unitOfWork.registerObject(address);
        if (!(addressClone1 == addressClone2)) {
            throw new TestErrorException("Registration fault: Clones are different for equal objects");
        }
    }

    protected void testRegisteringUnequalObjects() {
        /* This test will register two unequal objects
            In the first case the two objects are unequal and think that they are equal
            In the second case the two objects are unequal and know that they are unequal
            We should get exactly two different clones each time */
        Person person1 = Person.example1();
        Person person2 = Person.example2();

        Person personClone1 = (Person)this.unitOfWork.registerObject(person1);
        Person personClone2 = (Person)this.unitOfWork.registerObject(person2);
        if (personClone1 == personClone2) {
            throw new TestErrorException("Registration fault: Same clone returned for unequal objects");
        }
        MailAddress address1 = MailAddress.example1();
        MailAddress address2 = MailAddress.example2();
        MailAddress addressClone1 = (MailAddress)this.unitOfWork.registerObject(address1);
        MailAddress addressClone2 = (MailAddress)this.unitOfWork.registerObject(address2);
        if (addressClone1 == addressClone2) {
            throw new TestErrorException("Registration fault: Same clone returned for unequal objects");
        }
    }
}
