blob: 0e357760c248282ea215076f11ac28365e997339 [file] [log] [blame]
/*
* 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:
// ailitchev - Uni-directional OneToMany
package org.eclipse.persistence.testing.tests.unidirectional;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.SQLCall;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.tools.schemaframework.PopulationManager;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.unidirectional.*;
import org.eclipse.persistence.testing.tests.writing.ComplexUpdateTest;
/**
* This model tests reading/writing/deleting through using the employee demo.
*/
public class UnidirectionalEmployeeBasicTestModel extends TestModel {
/**
* Return the JUnit suite to allow JUnit runner to find it.
* Unfortunately JUnit only allows suite methods to be static,
* so it is not possible to generically do this.
*/
public static junit.framework.TestSuite suite() {
return new UnidirectionalEmployeeBasicTestModel();
}
public UnidirectionalEmployeeBasicTestModel() {
setDescription("This model tests reading/writing/deleting using the unidirectionl employee demo.");
}
@Override
public void addRequiredSystems() {
addRequiredSystem(new EmployeeSystem());
}
@Override
public void addTests() {
addTest(getReadObjectTestSuite());
addTest(getComplexUpdateObjectTestSuite());
addTest(getInsertObjectTestSuite());
addTest(getDeleteObjectTestSuite());
addTest(getReadAllTestSuite());
}
public static TestSuite getDeleteObjectTestSuite() {
TestSuite suite = new TestSuite();
suite.setName("EmployeeDeleteObjectTestSuite");
suite.setDescription("This suite tests the deletion of each object in the employee demo.");
Class employeeClass = org.eclipse.persistence.testing.models.unidirectional.Employee.class;
PopulationManager manager = PopulationManager.getDefaultManager();
suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0001")));
suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0002")));
suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0003")));
suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0004")));
suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0005")));
suite.addTest(new TargetLockingTest_DeleteSource(true));
suite.addTest(new TargetLockingTest_DeleteSource(false));
return suite;
}
public static TestSuite getInsertObjectTestSuite() {
TestSuite suite = new TestSuite();
suite.setName("EmployeeUOWBasicInsertObjectTestSuite");
suite.setDescription("This suite tests the insertion of each object in the employee demo using uow.");
EmployeePopulator system = new EmployeePopulator();
suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample1()));
suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample2()));
suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample3()));
suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample4()));
suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample5()));
return suite;
}
public static TestSuite getReadAllTestSuite() {
TestSuite suite = new TestSuite();
suite.setName("EmployeeReadAllTestSuite");
suite.setDescription("This suite tests the reading of all the objects of each class in the employee demo.");
suite.addTest(new ReadAllTest(Employee.class, 12));
suite.addTest(new ReadAllCallTest(Employee.class, 12, new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE")));
//Add new tests here ...
Expression orderBy = new ExpressionBuilder().get("firstName").ascending();
Call call = new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE");
suite.addTest(new ReadAllCallWithOrderingTest(Employee.class, 12, call, orderBy));
suite.addTest(new JoinTest());
suite.addTest(new JoinTest_SelectByFirstName());
suite.addTest(new BatchReadingTest());
suite.addTest(new BatchReadingTest_SelectByFirstName());
return suite;
}
public static TestSuite getReadObjectTestSuite() {
TestSuite suite = new TestSuite();
suite.setName("EmployeeReadObjectTestSuite");
suite.setDescription("This suite test the reading of each object in the employee demo.");
Class employeeClass = Employee.class;
PopulationManager manager = PopulationManager.getDefaultManager();
suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0001")));
suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0002")));
suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0003")));
suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0004")));
suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0005")));
Employee employee = (Employee)manager.getObject(employeeClass, "0001");
suite.addTest(new ReadObjectCallTest(employeeClass, new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE WHERE F_NAME = '"+employee.getFirstName()+"' AND L_NAME = '"+employee.getLastName()+"'")));
employee = (Employee)manager.getObject(employeeClass, "0002");
suite.addTest(new ReadObjectCallTest(employeeClass, new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE WHERE F_NAME = '"+employee.getFirstName()+"' AND L_NAME = '"+employee.getLastName()+"'")));
employee = (Employee)manager.getObject(employeeClass, "0003");
suite.addTest(new ReadObjectCallTest(employeeClass, new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE WHERE F_NAME = '"+employee.getFirstName()+"' AND L_NAME = '"+employee.getLastName()+"'")));
return suite;
}
public static TestSuite getComplexUpdateObjectTestSuite() {
TestSuite suite = new TestSuite();
suite.setName("EmployeeComplexUpdateTestSuite");
suite.setDescription("This suite tests the updating of each an employee by adding and/or removing managed employees and/or phones.");
Class employeeClass = Employee.class;
PopulationManager manager = PopulationManager.getDefaultManager();
Employee originalEmployee = (Employee)manager.getObject(employeeClass, "0001");
Employee otherEmployee = (Employee)manager.getObject(employeeClass, "0002");
// add a managed Employee from other Employee managed List; remove the first managed Employee.
suite.addTest(new EmployeeComplexUpdateTest(originalEmployee, otherEmployee.getManagedEmployees().get(0), originalEmployee.getManagedEmployees().get(0)));
// remove the first Phone.
suite.addTest(new EmployeeComplexUpdateTest(originalEmployee, (Object)null, originalEmployee.getPhoneNumbers().get(0)));
// add a managed Employee from other Employee managed List and new phone;
// remove the first two managed Employees and the first Phone.
Employee newEmployee = new Employee();
newEmployee.setFirstName("New");
PhoneNumber newPhoneNumber = new PhoneNumber("home", "001", "0000001");
suite.addTest(new EmployeeComplexUpdateTest(originalEmployee,
new Object[]{otherEmployee.getManagedEmployees().get(0), newEmployee, newPhoneNumber},
new Object[]{originalEmployee.getManagedEmployees().get(0), originalEmployee.getManagedEmployees().get(1), originalEmployee.getPhoneNumbers().get(0)}));
suite.addTest(new CascadeLockingTest());
suite.addTest(new TargetLockingTest_AddRemoveTarget());
return suite;
}
/**
* Tests adding/removing of target object to/from the source for UnidirectionalOneToManyMapping.
* Derived from ComplexUpdateTest, this test expects an instance of Employee as original object,
* as well as object (or array, or list) of objects to be added to the original objects as the second parameter,
* as well as object (or array, or list) of objects to be removed from the original objects as the third parameter.
* These objects should be of type either Employee or PhoneNumber.
*/
static class EmployeeComplexUpdateTest extends ComplexUpdateTest {
List<Employee> managedEmployeesToAdd = new ArrayList<Employee>();
List<Employee> managedEmployeesToRemove = new ArrayList<Employee>();
List<PhoneNumber> phonesToAdd = new ArrayList<PhoneNumber>();
List<PhoneNumber> phonesToRemove = new ArrayList<PhoneNumber>();
public EmployeeComplexUpdateTest(Employee originalEmployee, List objectsToAdd, Object objectToRemove) {
this(originalEmployee, (objectsToAdd != null ? objectsToAdd.toArray() : null), (objectToRemove != null ? new Object[]{objectToRemove} : null));
}
public EmployeeComplexUpdateTest(Employee originalEmployee, Object objectToAdd, List objectsToRemove) {
this(originalEmployee, (objectToAdd != null ? new Object[]{objectToAdd} : null), (objectsToRemove != null ? objectsToRemove.toArray() : null));
}
public EmployeeComplexUpdateTest(Employee originalEmployee, List objectsToAdd, List objectsToRemove) {
this(originalEmployee, (objectsToAdd != null ? objectsToAdd.toArray() : null), (objectsToRemove != null ? objectsToRemove.toArray() : null));
}
public EmployeeComplexUpdateTest(Employee originalEmployee, Object objectToAdd, Object objectToRemove) {
this(originalEmployee, (objectToAdd != null ? new Object[]{objectToAdd} : null), (objectToRemove != null ? new Object[]{objectToRemove} : null));
}
public EmployeeComplexUpdateTest(Employee originalEmployee, Object[] objectsToAdd, Object objectToRemove) {
this(originalEmployee, objectsToAdd, (objectToRemove != null ? new Object[]{objectToRemove} : null));
}
public EmployeeComplexUpdateTest(Employee originalEmployee, Object objectToAdd, Object[] objectsToRemove) {
this(originalEmployee, (objectToAdd != null ? new Object[]{objectToAdd} : null), objectsToRemove);
}
public EmployeeComplexUpdateTest(Employee originalEmployee, Object[] objectsToAdd, Object[] objectsToRemove) {
super(originalEmployee);
this.usesUnitOfWork = true;
if(objectsToAdd != null) {
for(int i=0; i < objectsToAdd.length; i++) {
Object objectToAdd = objectsToAdd[i];
if(objectToAdd instanceof Employee) {
if(!originalEmployee.getManagedEmployees().contains(objectToAdd)) {
managedEmployeesToAdd.add((Employee)objectToAdd);
} else {
throw new TestWarningException("OriginalEmployee: " + originalEmployee + " already manages employee to be added: " + objectToAdd);
}
} else {
// must be Phone
if(!originalEmployee.getPhoneNumbers().contains(objectToAdd)) {
phonesToAdd.add((PhoneNumber)objectToAdd);
} else {
throw new TestWarningException("OriginalEmployee: " + originalEmployee + " already has the phonee to be added: " + objectToAdd);
}
}
}
}
if(objectsToRemove != null) {
for(int i=0; i < objectsToRemove.length; i++) {
Object objectToRemove = objectsToRemove[i];
if(objectToRemove instanceof Employee) {
if(originalEmployee.getManagedEmployees().contains(objectToRemove)) {
managedEmployeesToRemove.add((Employee)objectToRemove);
} else {
throw new TestWarningException("OriginalEmployee: " + originalEmployee + " doesn't manage employee to be removed: " + objectToRemove);
}
} else {
// must be Phone
if(originalEmployee.getPhoneNumbers().contains(objectToRemove)) {
phonesToRemove.add((PhoneNumber)objectToRemove);
} else {
throw new TestWarningException("OriginalEmployee: " + originalEmployee + " doesn't have the phonee to be removed: " + objectToRemove);
}
}
}
}
// generate a meaningful test name
String employeeString = "";
if(managedEmployeesToAdd.size() > 0 || managedEmployeesToRemove.size() > 0 ) {
String addString = "";
if(managedEmployeesToAdd.size() > 0) {
addString = "add "+ managedEmployeesToAdd.size();
}
String removeString = "";
if(managedEmployeesToRemove.size() > 0) {
removeString = "remove "+ managedEmployeesToRemove.size();
}
employeeString = addString +(addString.length()>0 && removeString.length()>0 ? " and " : " ") + removeString + " Employees";
}
String phoneString = "";
if(phonesToAdd.size() > 0 || phonesToRemove.size() > 0 ) {
String addString = "";
if(phonesToAdd.size() > 0) {
addString = "add "+ phonesToAdd.size();
}
String removeString = "";
if(phonesToRemove.size() > 0) {
removeString = "remove "+ phonesToRemove.size();
}
phoneString = addString +(addString.length()>0 && removeString.length()>0 ? " and " : "") + removeString + " Phones";
}
setName("EmployeeComplexUpdateTest: " + employeeString +(employeeString.length()>0 && phoneString.length()>0 ? "; " : "")+ phoneString+";");
setDescription("The test updates original Employee object: " +originalObject.toString()+ " from the database by adding and/or removing managedEmployees and/or PhoneNumbers and verifies that the object updated correctly.");
}
@Override
public String getName() {
String testName = super.getName();
int lastIndex = testName.lastIndexOf(";");
if(lastIndex > 0) {
testName = testName.substring(0, lastIndex);
}
return testName;
}
@Override
protected void changeObject() {
UnitOfWork uow = (UnitOfWork)getSession();
Employee cloneEmployee = (Employee)workingCopy;
for(int i=0; i < managedEmployeesToAdd.size(); i++) {
Employee cloneEmployeeToAdd = (Employee)uow.registerObject(managedEmployeesToAdd.get(i));
cloneEmployee.addManagedEmployee(cloneEmployeeToAdd);
}
for(int i=0; i < managedEmployeesToRemove.size(); i++) {
Employee cloneEmployeeToRemove = (Employee)uow.registerObject(managedEmployeesToRemove.get(i));
cloneEmployee.removeManagedEmployee(cloneEmployeeToRemove);
}
for(int i=0; i < phonesToRemove.size(); i++) {
PhoneNumber clonePhoneToRemove = (PhoneNumber)uow.registerObject(phonesToRemove.get(i));
cloneEmployee.removePhoneNumber(clonePhoneToRemove);
}
for(int i=0; i < phonesToAdd.size(); i++) {
PhoneNumber clonePhoneToAdd = (PhoneNumber)uow.registerObject(phonesToAdd.get(i));
cloneEmployee.addPhoneNumber(clonePhoneToAdd);
}
}
@Override
protected void setup() {
super.setup();
for(int i=0; i < managedEmployeesToAdd.size(); i++) {
Employee readEmployeeToAdd = (Employee)readObject(managedEmployeesToAdd.get(i));
if(readEmployeeToAdd != null) {
managedEmployeesToAdd.set(i, readEmployeeToAdd);
} else {
// it's a new object
}
}
for(int i=0; i < managedEmployeesToRemove.size(); i++) {
Employee readEmployeeToRemove = (Employee)readObject(managedEmployeesToRemove.get(i));
if(readEmployeeToRemove != null) {
managedEmployeesToRemove.set(i, readEmployeeToRemove);
} else {
throw new TestWarningException("Employee to be removed: " + managedEmployeesToRemove.get(i) + " is not in the db");
}
}
for(int i=0; i < phonesToRemove.size(); i++) {
PhoneNumber readPhoneToRemove = (PhoneNumber)readObject(phonesToRemove.get(i));
if(readPhoneToRemove != null) {
phonesToRemove.set(i, readPhoneToRemove);
} else {
throw new TestWarningException("Phone to be removed: " + phonesToRemove.get(i) + " is not in the db");
}
}
for(int i=0; i < phonesToAdd.size(); i++) {
PhoneNumber readPhoneToAdd = (PhoneNumber)readObject(phonesToAdd.get(i));
if(readPhoneToAdd != null) {
phonesToAdd.set(i, readPhoneToAdd);
} else {
// it's a new object
}
}
}
protected Object readObject(Object object) {
ReadObjectQuery query = new ReadObjectQuery();
query.setSelectionObject(object);
return getSession().executeQuery(query);
}
}
/**
* Tests cascade locking of the source Employee object for adding, modifying and removing the target object (Employee and Phone).
* The version of he source should be always incremented on either adding or removing any target.
* Also currently source's version incremented on changing of the privately owned target (Phone),
* but on change of non private target (managed Employee) stays unchanged.
*/
static class CascadeLockingTest extends TransactionalTestCase {
long version[] = new long[7];
long versionExpected[] = new long[] {1, 2, 2, 3, 4, 5, 6};
public CascadeLockingTest() {
super();
setName("CascadeLockingPolicyTest");
setDescription("Tests optimistic lock cascading for UnidirectionalOneToManyMapping");
}
@Override
public void setup() {
super.setup();
for(int i=0; i<version.length; i++) {
version[i] = 0;
}
}
@Override
public void test() {
// setup
Employee manager = new Employee();
manager.setFirstName("Manager");
Employee employee = new Employee();
employee.setFirstName("Employee");
UnitOfWork uow = getSession().acquireUnitOfWork();
uow.registerObject(manager);
uow.registerObject(employee);
uow.commit();
version[0] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());
// test1 - add managed employee, manager's version should increment.
uow = getSession().acquireUnitOfWork();
Employee managerClone = (Employee)uow.registerObject(manager);
Employee employeeClone = (Employee)uow.registerObject(employee);
managerClone.addManagedEmployee(employeeClone);
uow.commit();
version[1] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());
// test2 - alter managed employee, manager's version should NOT increment.
uow = getSession().acquireUnitOfWork();
employeeClone = (Employee)uow.registerObject(employee);
employeeClone.setFirstName("Altered");
uow.commit();
version[2] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());
// test3- remove managed employee, manager's version should increment.
uow = getSession().acquireUnitOfWork();
managerClone = (Employee)uow.registerObject(manager);
employeeClone = (Employee)uow.registerObject(employee);
managerClone.removeManagedEmployee(employeeClone);
uow.commit();
version[3] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());
PhoneNumber phone = new PhoneNumber("home", "613", "1111111");
// test4 - add phone, manager's version should increment.
uow = getSession().acquireUnitOfWork();
managerClone = (Employee)uow.registerObject(manager);
PhoneNumber phoneClone = (PhoneNumber)uow.registerObject(phone);
managerClone.addPhoneNumber(phoneClone);
uow.commit();
version[4] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());
// test5- alter phone, manager's version should increment.
uow = getSession().acquireUnitOfWork();
phoneClone = (PhoneNumber)uow.registerObject(phone);
phoneClone.setType("work");
uow.commit();
version[5] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());
// test6- remove phone, manager's version should increment.
uow = getSession().acquireUnitOfWork();
managerClone = (Employee)uow.registerObject(manager);
phoneClone = (PhoneNumber)uow.registerObject(phone);
managerClone.removePhoneNumber(phoneClone);
uow.commit();
version[6] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());
}
@Override
public void verify() {
int numTestsFailed = 0;
String errorMsg = "";
for(int i=0; i<version.length; i++) {
if(version[i] + numTestsFailed != versionExpected[i]) {
numTestsFailed++;
errorMsg += "test" + i +" failed; ";
}
}
if(numTestsFailed > 0) {
throw new TestErrorException(errorMsg);
}
}
}
static class BatchReadingTest extends TestCase {
boolean shouldPrintDebugOutput = false;
public BatchReadingTest() {
setName("EmployeeBatchReadingTest - no selection criteria");
setDescription("Tests batch reading of Employees with batch expression managedEmployees.phoneNumbers");
}
void setSelectionCriteria(ReadAllQuery query) {
}
@Override
public void test() {
// clear cache
getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
// create batch read query, set its selectionCriteria
ReadAllQuery query = new ReadAllQuery(Employee.class);
setSelectionCriteria(query);
// before adding batch read attributes clone the query to create control query
ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
// add batch read attributes
Expression managedEmployees = query.getExpressionBuilder().get("managedEmployees");
Expression managedEmployeesPhoneNumbers = managedEmployees.get("phoneNumbers");
query.addBatchReadAttribute(managedEmployeesPhoneNumbers);
// execute the query
List employees = (List)getSession().executeQuery(query);
if(employees.isEmpty()) {
throw new TestProblemException("No Employees were read");
}
// need to instantiate only a single Phone on a single managed Employee to trigger sql that reads data from the db for all.
// still need to trigger all the indirections - but (except the first one) they are not accessing the db
// (the data is already cached in the value holders).
printDebug("Trigger batch reading results");
boolean isConnected = true;
for(int i=0; i < employees.size(); i++) {
Employee manager = (Employee)employees.get(i);
if(!manager.getManagedEmployees().isEmpty()) {
printDebug("Manager = " + manager);
for(int j=0; j < manager.getManagedEmployees().size(); j++) {
Employee emp = (Employee)manager.getManagedEmployees().get(j);
printDebug(" " + emp);
for(int k = 0; k < emp.getPhoneNumbers().size(); k++) {
if(isConnected) {
// need to instantiate only a single Phone on a single managed Employee to trigger sql that reads data from the db for all.
// to ensure that no other sql is issued close connection.
((AbstractSession)getSession()).getAccessor().closeConnection();
isConnected = false;
}
PhoneNumber phone = (PhoneNumber)emp.getPhoneNumbers().get(k);
printDebug(" " + phone);
}
}
} else {
printDebug(manager.toString());
}
}
if(!isConnected) {
// reconnect connection
((AbstractSession)getSession()).getAccessor().reestablishConnection((AbstractSession)getSession());
}
printDebug("");
// obtain control results
// clear cache
getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
// execute control query
List controlEmployees = (List)getSession().executeQuery(controlQuery);
// instantiate all value holders that the batch query expected to instantiate
printDebug("Trigger control results");
for(int i=0; i < controlEmployees.size(); i++) {
Employee manager = (Employee)controlEmployees.get(i);
if(!manager.getManagedEmployees().isEmpty()) {
printDebug("Manager = " + manager);
for(int j=0; j < manager.getManagedEmployees().size(); j++) {
Employee emp = (Employee)manager.getManagedEmployees().get(j);
printDebug(" " + emp);
for(int k = 0; k < emp.getPhoneNumbers().size(); k++) {
PhoneNumber phone = (PhoneNumber)emp.getPhoneNumbers().get(k);
printDebug(" " + phone);
}
}
} else {
printDebug(manager.toString());
}
}
// compare results
String errorMsg = JoinedAttributeTestHelper.compareCollections(employees, controlEmployees, getSession().getClassDescriptor(Employee.class), ((AbstractSession)getSession()));
if(errorMsg.length() > 0) {
throw new TestErrorException(errorMsg);
}
}
void printDebug(String msg) {
if(shouldPrintDebugOutput) {
System.out.println(msg);
}
}
}
static class BatchReadingTest_SelectByFirstName extends BatchReadingTest {
public BatchReadingTest_SelectByFirstName() {
super();
setName("EmployeeBatchReadingTest - select by first name");
}
@Override
void setSelectionCriteria(ReadAllQuery query) {
query.setSelectionCriteria(query.getExpressionBuilder().get("firstName").like("J%"));
}
}
static class JoinTest extends TestCase {
public JoinTest() {
super();
setName("JoinTest - no selection criteria");
setDescription("Tests reading of Employees with join expressions anyOf(managedEmployees) and anyOf(managedEmployees).anyOf(phoneNumbers)");
}
void setSelectionCriteria(ReadAllQuery query) {
}
@Override
public void test() {
ReadAllQuery query = new ReadAllQuery();
query.setReferenceClass(Employee.class);
setSelectionCriteria(query);
ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
Expression employees = query.getExpressionBuilder().anyOf("managedEmployees");
query.addJoinedAttribute(employees);
Expression phones = employees.anyOf("phoneNumbers");
query.addJoinedAttribute(phones);
String errorMsg = JoinedAttributeTestHelper.executeQueriesAndCompareResults(controlQuery, query, (AbstractSession)getSession());
if(errorMsg.length() > 0) {
throw new TestErrorException(errorMsg);
}
}
}
static class JoinTest_SelectByFirstName extends JoinTest {
public JoinTest_SelectByFirstName() {
super();
setName("JoinTest - select by first name");
}
@Override
void setSelectionCriteria(ReadAllQuery query) {
query.setSelectionCriteria(query.getExpressionBuilder().get("firstName").like("J%"));
}
}
/**
* Base class for TargetLockingTest_AddRemoveTarget and TargetLockingTest_DeleteSource.
* and mapping's shouldIncrementTargetLockValueOnAddOrRemoveTarget flag is set to true (default setting)
* adding/removing target to/from source causes target's version to increment.
*/
static class TargetLockingTest extends TestCase {
Employee employee[];
public TargetLockingTest() {
super();
}
long getVersion(Employee emp) {
return (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(emp, emp.getId(), getAbstractSession());
}
@Override
public void reset() {
UnitOfWork uow = getSession().acquireUnitOfWork();
for(int i=0; i<employee.length; i++) {
if(employee[i] != null) {
uow.deleteObject(employee[i]);
}
}
uow.commit();
}
}
/**
* If target descriptor of UnidirectionalOneToMany mapping has optimistic locking policy,
* and mapping's shouldIncrementTargetLockValueOnAddOrRemoveTarget flag is set to true (default setting)
* adding/removing target to/from source causes target's version to increment.
*/
static class TargetLockingTest_AddRemoveTarget extends TargetLockingTest {
public TargetLockingTest_AddRemoveTarget() {
super();
setName("TargetLockingTest_AddRemoveTarget");
setDescription("Tests target optimistic locking for UnidirectionalOneToManyMapping when targets are added to and removed from the source.");
}
@Override
public void setup() {
// create 5 Employees.
employee = new Employee[5];
employee[0] = new Employee();
employee[0].setFirstName("Manager");
// 1 and 2 have manager 0.
employee[1] = new Employee();
employee[1].setFirstName("Employee_1");
employee[0].addManagedEmployee(employee[1]);
employee[2] = new Employee();
employee[2].setFirstName("Employee_2");
employee[0].addManagedEmployee(employee[2]);
// 3 and 4 don't have a manager.
employee[3] = new Employee();
employee[3].setFirstName("Employee_3");
employee[4] = new Employee();
employee[4].setFirstName("Employee_4");
// insert all the Employees into the db.
UnitOfWork uow = getSession().acquireUnitOfWork();
for(int i=0; i<employee.length; i++) {
uow.registerObject(employee[i]);
}
uow.commit();
}
@Override
public void test() {
UnitOfWork uow = getSession().acquireUnitOfWork();
Employee managerClone = (Employee)uow.registerObject(employee[0]);
// remove all managed Employees (1 and 2)
managerClone.getManagedEmployees().clear();
// add to managed list new Employees (3 and 4)
Employee employee3Clone = (Employee)uow.registerObject(employee[3]);
Employee employee4Clone = (Employee)uow.registerObject(employee[4]);
managerClone.addManagedEmployee(employee3Clone);
managerClone.addManagedEmployee(employee4Clone);
// after commit the versions of all Employees should be changed.
uow.commit();
}
@Override
public void verify() {
long version[] = new long[employee.length];
String errorMsg = "";
for(int i=0; i<employee.length; i++) {
version[i] = getVersion(employee[i]);
if(version[i] != 2) {
errorMsg += "in the cache version["+i+"] = "+version[i]+" (2 was expected); ";
}
}
// make sure that versions in the db are correct, too.
for(int i=0; i<employee.length; i++) {
employee[i] = (Employee)getSession().refreshObject(employee[i]);
version[i] = getVersion(employee[i]);
if(version[i] != 2) {
errorMsg += "in the db version["+i+"] = "+version[i]+" (2 was expected); ";
}
}
if(errorMsg.length() > 0) {
throw new TestErrorException(errorMsg);
}
}
}
/**
* If target descriptor of UnidirectionalOneToMany mapping has optimistic locking policy,
* and mapping's shouldIncrementTargetLockValueOnDeleteSource flag is set to true (default setting)
* the deleting the source source causes all targets' versions to increment.
* Note that in this case the indirection is triggered to make sure that the proper targets' versions used.
*/
static class TargetLockingTest_DeleteSource extends TargetLockingTest {
boolean isIndirectionTriggered;
public TargetLockingTest_DeleteSource(boolean isIndirectionTriggered) {
super();
this.isIndirectionTriggered = isIndirectionTriggered;
setName("TargetLockingTest_DeleteSource");
if(isIndirectionTriggered) {
setName(getName() + "_IndirectionTriggered");
} else {
setName(getName() + "_IndirectionNotTriggered");
}
setDescription("Tests target optimistic locking for UnidirectionalOneToManyMapping when the source is deleted.");
}
@Override
public void setup() {
// create 3 Employees.
employee = new Employee[3];
employee[0] = new Employee();
employee[0].setFirstName("Manager");
// 1 and 2 have manager 0.
employee[1] = new Employee();
employee[1].setFirstName("Employee_1");
employee[0].addManagedEmployee(employee[1]);
employee[2] = new Employee();
employee[2].setFirstName("Employee_2");
employee[0].addManagedEmployee(employee[2]);
// insert all the Employees into the db.
UnitOfWork uow = getSession().acquireUnitOfWork();
for(int i=0; i<employee.length; i++) {
uow.registerObject(employee[i]);
}
uow.commit();
getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
}
@Override
public void test() {
employee[0] = (Employee)getSession().readObject(employee[0]);
if(isIndirectionTriggered) {
// that triggers indirection.
employee[0].getManagedEmployees().size();
}
UnitOfWork uow = getSession().acquireUnitOfWork();
Employee managerClone = (Employee)uow.deleteObject(employee[0]);
// after commit 0 is deleted and the versions of 1 and 2 should be changed.
uow.commit();
// set the deleted Employee to null so that reset method won't attempt to delete it again.
employee[0] = null;
}
@Override
public void verify() {
long version[] = new long[employee.length];
String errorMsg = "";
for(int i=1; i<employee.length; i++) {
version[i] = getVersion(employee[i]);
if(version[i] != 2) {
errorMsg += "in the cache version["+i+"] = "+version[i]+" (2 was expected); ";
}
}
// make sure that versions in the db are correct, too.
for(int i=1; i<employee.length; i++) {
employee[i] = (Employee)getSession().refreshObject(employee[i]);
version[i] = getVersion(employee[i]);
if(version[i] != 2) {
errorMsg += "in the db version["+i+"] = "+version[i]+" (2 was expected); ";
}
}
if(errorMsg.length() > 0) {
throw new TestErrorException(errorMsg);
}
}
}
}