package er.erxtest.tests; import java.util.Enumeration; import java.util.UUID; import junit.framework.AssertionFailedError; import junit.framework.Test; import junit.framework.TestSuite; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.eocontrol.EOEnterpriseObject; import com.webobjects.eocontrol.EOObjectStore; import com.webobjects.foundation.NSArray; import er.erxtest.ERXTestCase; import er.erxtest.model.Company; import er.erxtest.model.Employee; import er.extensions.eof.ERXEC; import er.extensions.eof.ERXEOControlUtilities; import er.extensions.eof.ERXObjectStoreCoordinatorPool; /** * Run this with ERXMainRunner. * * @author mschrag */ public class ERXObjectStoreCoordinatorSynchronizerTestCase extends ERXTestCase { public static Test suite() throws Exception { TestSuite suite = new TestSuite(); suite.addTestSuite(ERXObjectStoreCoordinatorSynchronizerTestCase.class); return suite; } public void testPool() { assertNotNull(ERXObjectStoreCoordinatorPool._pool()); assertNotNull(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); } public void testDifferenceStores() { EOObjectStore osc1 = ERXObjectStoreCoordinatorPool._pool().nextObjectStore(); EOObjectStore osc2 = ERXObjectStoreCoordinatorPool._pool().nextObjectStore(); assertNotSame(osc1, osc2); } public void testInsertEO() { // Create Company in OSC1 String companyName = "Company" + UUID.randomUUID().toString(); EOEditingContext editingContext_osc1 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc1 = Company.createCompany(editingContext_osc1, companyName); editingContext_osc1.saveChanges(); Company company_osc1_fetched = Company.fetchCompany(editingContext_osc1, Company.NAME_KEY, companyName); assertNotNull(company_osc1_fetched); sleep(); // Fetch Company in OSC2 EOEditingContext editingContext_osc2 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc2 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName); assertNotNull(company_osc2); assertEquals(companyName, company_osc1.name()); assertEquals(companyName, company_osc2.name()); } public void testUpdateEO() { // Create Company1 in OSC1 String companyName = "Company" + UUID.randomUUID().toString(); EOEditingContext editingContext_osc1 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc1 = Company.createCompany(editingContext_osc1, companyName); editingContext_osc1.saveChanges(); sleep(); // Fetch Company1 in OSC2 EOEditingContext editingContext_osc2 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc2 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName); assertNotNull(company_osc2); for (int i = 0; i < 10; i++) { // Change Company1's name in OSC1 String companyName_1 = "Company" + UUID.randomUUID().toString() + "_osc1"; company_osc1.setName(companyName_1); editingContext_osc1.saveChanges(); sleep(); assertEquals(companyName_1, company_osc2.name()); assertEquals(companyName_1, company_osc1.name()); // Fetch Company1 by name in OSC1 Company company_osc1_with_companyName1 = Company.fetchCompany(editingContext_osc1, Company.NAME_KEY, companyName_1); assertEquals(company_osc1, company_osc1_with_companyName1); // Fetch Company1 by name in OSC2 Company company_osc2_with_companyName1 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName_1); assertEquals(company_osc2, company_osc2_with_companyName1); // Change Company1's name in OSC2 String companyName_2 = "Company" + UUID.randomUUID().toString() + "_osc2"; company_osc2.setName(companyName_2); editingContext_osc2.saveChanges(); sleep(); assertEquals(companyName_2, company_osc1.name()); assertEquals(companyName_2, company_osc2.name()); // Fetch Company1 by name in OSC1 Company company_osc1_with_companyName2 = Company.fetchCompany(editingContext_osc1, Company.NAME_KEY, companyName_2); assertEquals(company_osc1, company_osc1_with_companyName2); // Fetch Company1 by name in OSC2 Company company_osc2_with_companyName2 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName_2); assertEquals(company_osc2, company_osc2_with_companyName2); } } public void testMergeEOChanges() { // Create Company1 in OSC1 String companyName = "Company" + UUID.randomUUID().toString(); EOEditingContext editingContext_osc1 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc1 = Company.createCompany(editingContext_osc1, companyName); editingContext_osc1.saveChanges(); sleep(); // Fetch Company1 in OSC2 EOEditingContext editingContext_osc2 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc2 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName); assertNotNull(company_osc2); for (int i = 0; i < 10; i++) { // Change Company1's name in OSC1 String companyName_1 = "Company" + UUID.randomUUID().toString() + "_osc1"; String companyAddress1_1 = company_osc1.address1(); company_osc1.setName(companyName_1); // Change Company1's address in OSC2 String companyAddress1_2 = "Address" + UUID.randomUUID().toString() + "_osc2"; company_osc2.setAddress1(companyAddress1_2); // Save Company1's new name in OSC1, address in OSC2 should be untouched but merged with new name editingContext_osc1.saveChanges(); sleep(); assertEquals(companyName_1, company_osc2.name()); assertEquals(companyName_1, company_osc1.name()); assertEquals(companyAddress1_2, company_osc2.address1()); assertEquals(companyAddress1_1, company_osc1.address1()); // Fetch Company1 by name in OSC1 Company company_osc1_with_companyName1 = Company.fetchCompany(editingContext_osc1, Company.NAME_KEY, companyName_1); assertEquals(company_osc1, company_osc1_with_companyName1); assertEquals(companyAddress1_1, company_osc1_with_companyName1.address1()); // Fetch Company1 by name in OSC2 Company company_osc2_with_companyName1 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName_1); assertEquals(company_osc2, company_osc2_with_companyName1); assertEquals(companyAddress1_2, company_osc2_with_companyName1.address1()); // Save Company1's new address in OSC2 editingContext_osc2.saveChanges(); sleep(); assertEquals(companyName_1, company_osc1.name()); assertEquals(companyName_1, company_osc2.name()); assertEquals(companyAddress1_2, company_osc2.address1()); assertEquals(companyAddress1_2, company_osc1.address1()); } } public void testAddToUnfaultedToMany() { // Create Company1 in OSC1 String companyName = "Company" + UUID.randomUUID().toString(); EOEditingContext editingContext_osc1 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc1 = Company.createCompany(editingContext_osc1, companyName); editingContext_osc1.saveChanges(); // Fetch Company1 in OSC2 EOEditingContext editingContext_osc2 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc2 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName); assertNotNull(company_osc2); // Create and Save Employee1 in Company1 in OSC1 String employeeFirstName = "Employee" + UUID.randomUUID().toString(); String employeeLastName = "Jones"; Employee employee_osc1 = Employee.createEmployee(editingContext_osc1, employeeFirstName, employeeLastName, Boolean.FALSE, company_osc1); editingContext_osc1.saveChanges(); // Fetch employees relationship of Company1 in OSC1 assertContainsExactlyEOs(new NSArray<>(employee_osc1), company_osc1.employees()); // Fetch employees relationship of Company1 in OSC2 assertContainsExactlyEOs(new NSArray<>(employee_osc1), company_osc2.employees()); } public void testAddToFaultedToMany() { // Create Company1 in OSC1 String companyName = "Company" + UUID.randomUUID().toString(); EOEditingContext editingContext_osc1 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc1 = Company.createCompany(editingContext_osc1, companyName); editingContext_osc1.saveChanges(); sleep(); // Fetch employees for Company1 in OSC1 @SuppressWarnings("unused") NSArray employees_osc1 = company_osc1.employees(); // Fetch Company1 in OSC2 EOEditingContext editingContext_osc2 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc2 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName); assertNotNull(company_osc2); // Fetch employees for Company1 in OSC2 @SuppressWarnings("unused") NSArray employees_osc2 = company_osc2.employees(); // Create and Save Employee1 for Company1 in OSC1 String employeeFirstName = "Employee" + UUID.randomUUID().toString(); String employeeLastName = "Jones"; Employee employee_osc1 = Employee.createEmployee(editingContext_osc1, employeeFirstName, employeeLastName, Boolean.FALSE, company_osc1); editingContext_osc1.saveChanges(); sleep(); // Check employees for Company1 in OSC1 assertContainsExactlyEOs(new NSArray<>(employee_osc1), company_osc1.employees()); // Check employees for Company1 in OSC2 assertContainsExactlyEOs(new NSArray<>(employee_osc1), company_osc2.employees()); // Create employee for Company1 in OSC2 and Save String employeeFirstName2 = "Employee" + UUID.randomUUID().toString(); String employeeLastName2 = "Jones"; Employee employee_osc2 = Employee.createEmployee(editingContext_osc2, employeeFirstName2, employeeLastName2, Boolean.FALSE, company_osc2); editingContext_osc2.saveChanges(); sleep(); // Check employees for Company1 in OSC1 assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee_osc1, employee_osc2 }), company_osc1.employees()); // Check employees for Company1 in OSC2 assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee_osc1, employee_osc2 }), company_osc2.employees()); } public void testAddToFaultedToManyWithUncommittedToManyEntries() { // Create Company1 in OSC1 String companyName = "Company" + UUID.randomUUID().toString(); EOEditingContext editingContext_osc1 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc1 = Company.createCompany(editingContext_osc1, companyName); editingContext_osc1.saveChanges(); sleep(); // Fetch Company1 in OSC2 EOEditingContext editingContext_osc2 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc2 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName); assertNotNull(company_osc2); // Create (but do not save) Employee1 for Company1 in OSC2 String employeeFirstName1 = "Employee" + UUID.randomUUID().toString(); String employeeLastName1 = "Jones"; Employee employee1_osc2 = Employee.createEmployee(editingContext_osc2, employeeFirstName1, employeeLastName1, Boolean.FALSE, company_osc2); // Check employees for Company1 in OSC1 (should contain uncommitted Employee) NSArray employees_osc2_BeforeInsert = company_osc2.employees(); assertEquals(1, employees_osc2_BeforeInsert.count()); assertEOEquals(employee1_osc2, employees_osc2_BeforeInsert.objectAtIndex(0)); // Create and save Employee2 for Company1 in OSC1 String employeeFirstName2 = "Employee" + UUID.randomUUID().toString(); String employeeLastName2 = "Jones"; Employee employee2_osc1 = Employee.createEmployee(editingContext_osc1, employeeFirstName2, employeeLastName2, Boolean.FALSE, company_osc1); editingContext_osc1.saveChanges(); sleep(); // Check employees for Company1 in OSC2 (should contain both Employees) assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee1_osc2, employee2_osc1 }), company_osc2.employees()); // Check employees for Company1 in OSC1 (should contain only Employee2) assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee2_osc1 }), company_osc1.employees()); // Save Employee1 in OSC2 editingContext_osc2.saveChanges(); sleep(); // Check employees for Company1 in OSC2 (should contain both Employees) assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee1_osc2, employee2_osc1 }), company_osc2.employees()); // Check employees for Company1 in OSC1 (should contain both Employees) assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee1_osc2, employee2_osc1 }), company_osc1.employees()); } public void testRemoveFromFaultedToMany() { // Create Company1 in OSC1 String companyName = "Company" + UUID.randomUUID().toString(); EOEditingContext editingContext_osc1 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc1 = Company.createCompany(editingContext_osc1, companyName); editingContext_osc1.saveChanges(); sleep(); // Create and Save Employee1 and Employee2 for Company1 in OSC1 String employeeFirstName1 = "Employee" + UUID.randomUUID().toString(); String employeeLastName1 = "Jones"; Employee employee1_osc1 = Employee.createEmployee(editingContext_osc1, employeeFirstName1, employeeLastName1, Boolean.FALSE, company_osc1); String employeeFirstName2 = "Employee" + UUID.randomUUID().toString(); String employeeLastName2 = "Jones"; Employee employee2_osc1 = Employee.createEmployee(editingContext_osc1, employeeFirstName2, employeeLastName2, Boolean.FALSE, company_osc1); editingContext_osc1.saveChanges(); sleep(); // Fetch employees for Company1 in OSC1 assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee1_osc1, employee2_osc1 }), company_osc1.employees()); // Fetch Company1 in OSC2 EOEditingContext editingContext_osc2 = ERXEC.newEditingContext(ERXObjectStoreCoordinatorPool._pool().nextObjectStore()); Company company_osc2 = Company.fetchCompany(editingContext_osc2, Company.NAME_KEY, companyName); assertNotNull(company_osc2); // Fetch and check employees for Company1 in OSC2 assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee1_osc1, employee2_osc1 }), company_osc2.employees()); // gonna break NSArray employees_osc2 = company_osc2.employees(); Employee employee2_osc2 = (Employee) employees_osc2.objectAtIndex(0); Employee employee1_osc2 = (Employee) employees_osc2.objectAtIndex(1); Employee secondEmployee_osc2; if (ERXEOControlUtilities.eoEquals(employee1_osc1, employee1_osc2)) { secondEmployee_osc2 = employee2_osc2; } else { secondEmployee_osc2 = employee1_osc2; } NSArray<Employee> holdingOnToEmployees = company_osc2.employees(); assertEquals(2, holdingOnToEmployees.count()); for (Employee employee : holdingOnToEmployees) { assertNotNull(employee); assertNotNull(employee.firstName()); } NSArray<Employee> holdingOnToUntouchedEmployees = company_osc2.employees(); assertEquals(2, holdingOnToUntouchedEmployees.count()); // Delete Employee1 in OSC1 and Save editingContext_osc1.deleteObject(employee1_osc1); editingContext_osc1.saveChanges(); sleep(); // Test that the deleted object is technically still in our EC assertEquals(2, holdingOnToEmployees.count()); for (Employee employee : holdingOnToEmployees) { assertNotNull(employee); assertNotNull(employee.firstName()); } // Test that the deleted object is technically still in our EC assertEquals(2, holdingOnToUntouchedEmployees.count()); for (Employee employee : holdingOnToUntouchedEmployees) { assertNotNull(employee); assertNotNull(employee.firstName()); } // for (Employee employee : holdingOnToEmployees) { // employee.setName(employee.name() + " Modified"); // } // try { // editingContext_osc2.saveChanges(); // throw new AssertionFailedError("This should have failed."); // } // catch (EOGeneralAdaptorException e) { // // expected // } // Fetch and check employees for Company1 in OSC1 assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee2_osc1 }), company_osc1.employees()); // Fetch and check employees for Company1 in OSC2 assertContainsExactlyEOs(new NSArray<>(new Employee[] { employee2_osc1 }), company_osc2.employees()); // ... Do someting with the deleted object in OSC2 // Delete the remaining employee in OSC2 and Save editingContext_osc2.deleteObject(secondEmployee_osc2); editingContext_osc2.saveChanges(); sleep(); // Fetch and check employees for Company1 in OSC1 assertContainsExactlyEOs(NSArray.EmptyArray, company_osc1.employees()); // Fetch and check employees for Company1 in OSC2 assertContainsExactlyEOs(NSArray.EmptyArray, company_osc2.employees()); } public static void assertEOEquals(Object obj1, Object obj2) { if (obj1 != null && obj2 != null && obj1 instanceof EOEnterpriseObject && obj2 instanceof EOEnterpriseObject) { EOEnterpriseObject eo1 = (EOEnterpriseObject) obj1; EOEnterpriseObject eo2 = (EOEnterpriseObject) obj2; if (!ERXEOControlUtilities.eoEquals(eo1, eo2)) { throw new AssertionFailedError("Expected " + eo1.editingContext().globalIDForObject(eo1) + ", but got " + eo2.editingContext().globalIDForObject(eo2)); } } else { assertEquals(obj1, obj2); } } public void assertContainsExactlyEOs(NSArray expectedEOs, NSArray actualEOs) { int expectedCount = expectedEOs.count(); int actualCount = actualEOs.count(); assertEquals(expectedCount, actualCount); Enumeration expectedEOsEnum = expectedEOs.objectEnumerator(); while (expectedEOsEnum.hasMoreElements()) { EOEnterpriseObject expectedEO = (EOEnterpriseObject) expectedEOsEnum.nextElement(); boolean containsEO = false; Enumeration actualEOsEnum = actualEOs.objectEnumerator(); while (!containsEO && actualEOsEnum.hasMoreElements()) { EOEnterpriseObject actualEO = (EOEnterpriseObject) actualEOsEnum.nextElement(); containsEO = ERXEOControlUtilities.eoEquals(expectedEO, actualEO); } if (!containsEO) { throw new AssertionFailedError("Expected " + expectedEOs.valueForKey("__globalID") + ", but got " + actualEOs.valueForKey("__globalID")); } } } protected void sleep() { try { Thread.sleep(50); } catch (Throwable t) { } } }