/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apereo.portal.groups; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Random; import junit.framework.TestCase; import junit.textui.TestRunner; import org.apereo.portal.EntityIdentifier; import org.apereo.portal.IBasicEntity; import org.apereo.portal.jdbc.RDBMServices; import org.apereo.portal.security.IPerson; import org.apereo.portal.services.GroupService; import org.apereo.portal.spring.locator.EntityTypesLocator; /** * Tests the groups framework (a start). */ public class GroupsTester extends TestCase { private static Class GROUP_CLASS; private static Class IPERSON_CLASS; private static Class TEST_ENTITY_CLASS; private static String CR = "\n"; private IEntity[] testEntities; private String[] testEntityKeys; private int numTestEntities = 0; private Random random = new Random(); private class TestEntity implements IBasicEntity { private EntityIdentifier entityIdentifier; private TestEntity(String entityKey) { super(); entityIdentifier = new EntityIdentifier(entityKey, this.getClass()); } public EntityIdentifier getEntityIdentifier() { return entityIdentifier; } public boolean equals(Object o) { if (o == null) return false; if (!(o instanceof IBasicEntity)) return false; IBasicEntity ent = (IBasicEntity) o; return ent.getEntityIdentifier().equals(getEntityIdentifier()); } public String toString() { return "TestEntity(" + getEntityIdentifier().getKey() + ")"; } } private class GroupsReadTester implements Runnable { protected IEntityGroup group = null; protected int numTests = 0; protected String testerID = null; protected String printID = null; protected GroupsReadTester(String id, IEntityGroup g, int tests) { super(); group = g; numTests = tests; testerID = id; } public void run() { printID = "Tester " + testerID; print(printID + " starting."); for (int i = 0; i < numTests; i++) { // print(printID + " running test # " + (i+1)); try { runTest(); } catch (GroupsException ge) { } int sleepMillis = random.nextInt(20); // print(printID + " will now sleep for " + sleepMillis + " ms."); try { Thread.sleep(sleepMillis); } catch (Exception ex) { } } } private void runTest() throws GroupsException { int numMembers = 0, numContainingGroups = 0; numMembers = group.getChildren().size(); numContainingGroups = group.getParentGroups().size(); // print (printID + " members: " + numMembers + " entities: " + numEntities + " containing groups: " + numContainingGroups); } } /** EntityLockTester constructor comment. */ public GroupsTester(String name) { super(name); } protected void addTestEntityType() { try { EntityTypesLocator.getEntityTypes() .addEntityTypeIfNecessary(TEST_ENTITY_CLASS, "Test Entity Type"); } catch (Exception ex) { print("GroupsTester.addTestEntityType(): " + ex.getMessage()); } } protected void deleteTestEntityType() { try { EntityTypesLocator.getEntityTypes().deleteEntityType(TEST_ENTITY_CLASS); } catch (Exception ex) { print("EntityCacheTester.deleteTestEntityType(): " + ex.getMessage()); } } protected void deleteTestGroups() { String sql = " FROM UP_GROUP WHERE ENTITY_TYPE_ID = " + EntityTypesLocator.getEntityTypes() .getEntityIDFromType(TEST_ENTITY_CLASS); String selectSql = "SELECT GROUP_ID" + sql; String deleteSql = "DELETE" + sql; String deleteMemberSql = "DELETE FROM UP_GROUP_MEMBERSHIP WHERE GROUP_ID = "; Connection conn = null; try { conn = RDBMServices.getConnection(); Statement selectStmnt = conn.createStatement(); ResultSet rs = selectStmnt.executeQuery(selectSql); while (rs.next()) { String key = rs.getString(1); Statement deleteMemberStmnt = conn.createStatement(); int memberRC = deleteMemberStmnt.executeUpdate(deleteMemberSql + "'" + key + "'"); print("Test member rows deleted: " + memberRC); } Statement deleteGroupStmnt = conn.createStatement(); int rc = deleteGroupStmnt.executeUpdate(deleteSql); print("Test group rows deleted: " + rc); } catch (Exception ex) { print("GroupsTester.deleteTestGroups(): " + ex.getMessage()); } finally { RDBMServices.releaseConnection(conn); } } /** @return org.apereo.portal.groups.IEntityGroup */ private IEntityGroup findGroup(String key) throws GroupsException { IEntityGroup group = GroupService.findGroup(key); return group; } /** @return org.apereo.portal.groups.ILockableEntityGroup */ private ILockableEntityGroup findLockableGroup(String key) throws GroupsException { String owner = "de3"; ILockableEntityGroup group = GroupService.findLockableGroup(key, owner); return group; } /** @return org.apereo.portal.services.GroupService */ private Collection getAllGroupMembers(IGroupMember gm) throws GroupsException { Collection list = new ArrayList(); if (gm.isGroup()) { for (IGroupMember descendant : gm.asGroup().getDescendants()) { list.add(descendant); } } return list; } /** @return RDBMEntityStore */ private IEntityStore getEntityStore() throws GroupsException { return RDBMEntityStore.singleton(); } /** @return org.apereo.portal.services.GroupService */ private Collection getGroupMembers(IGroupMember gm) throws GroupsException { Collection list = new ArrayList(); if (gm.isGroup()) { for (Iterator itr = gm.asGroup().getChildren().iterator(); itr.hasNext(); ) { list.add(itr.next()); } } return list; } /** @return RDBMEntityGroupStore */ private RDBMEntityGroupStore getGroupStore() throws GroupsException { return RDBMEntityGroupStore.singleton(); } /** @return org.apereo.portal.groups.IEntity */ private IEntity getNewEntity(String key) throws GroupsException { return GroupService.getEntity(key, TEST_ENTITY_CLASS); } /** @return org.apereo.portal.groups.IEntityGroup */ private IEntityGroup getNewGroup() throws GroupsException { IEntityGroup group = GroupService.newGroup(TEST_ENTITY_CLASS); group.setName("name_" + group.getKey()); group.setCreatorID("de3"); return group; } /** * @return java.lang.String * @param length int */ private String getRandomString(java.util.Random r, int length) { char[] chars = new char[length]; for (int i = 0; i < length; i++) { int diff = (r.nextInt(25)); int charValue = (int) 'A' + diff; chars[i] = (char) charValue; } return new String(chars); } /** * Starts the application. * * @param args an array of command-line arguments */ public static void main(java.lang.String[] args) throws Exception { String[] mainArgs = {"org.apereo.portal.concurrency.caching.EntityCacheTester"}; print("START TESTING CACHE"); printBlankLine(); TestRunner.main(mainArgs); printBlankLine(); print("END TESTING CACHE"); } private static void print(IEntity[] entities) { for (int i = 0; i < entities.length; i++) { print("(" + (i + 1) + ") " + entities[i]); } print(" Total: " + entities.length); } /** @param msg java.lang.String */ private static void print(String msg) { java.sql.Timestamp ts = new java.sql.Timestamp(System.currentTimeMillis()); System.out.println(ts + " : " + msg); } private static void printBlankLine() { System.out.println(""); } protected void setUp() { try { if (GROUP_CLASS == null) { GROUP_CLASS = Class.forName("org.apereo.portal.groups.IEntityGroup"); } if (IPERSON_CLASS == null) { IPERSON_CLASS = Class.forName("org.apereo.portal.security.IPerson"); } if (TEST_ENTITY_CLASS == null) { TEST_ENTITY_CLASS = TestEntity.class; } addTestEntityType(); numTestEntities = 100; // Entities and their keys: testEntityKeys = new String[numTestEntities]; testEntities = new IEntity[numTestEntities]; for (int i = 0; i < numTestEntities; i++) { testEntityKeys[i] = (getRandomString(random, 3) + i); testEntities[i] = getNewEntity(testEntityKeys[i]); } } catch (Exception ex) { print("GroupsTester.setUp(): " + ex.getMessage()); } } protected void tearDown() { try { testEntityKeys = null; testEntities = null; deleteTestGroups(); deleteTestEntityType(); } catch (Exception ex) { print("GroupTester.tearDown(): " + ex.getMessage()); } } public void testAddAndDeleteGroups() throws Exception { print(CR + "***** ENTERING GroupsTester.testAddAndDeleteGroups() *****" + CR); String msg = null; msg = "Creating a new IEntityGroup."; print(msg); IEntityGroup newGroup = getNewGroup(); assertNotNull(msg, newGroup); print("Now updating " + newGroup); newGroup.setName("Test"); newGroup.setCreatorID("de3"); newGroup.update(); print("Now retrieving group just created from the store."); String key = newGroup.getKey(); IEntityGroup retrievedGroup = GroupService.findGroup(key); msg = "Testing retrieved group."; print(msg); assertEquals(msg, newGroup, retrievedGroup); print("Now deleting group just created from the store."); retrievedGroup.delete(); print("Attempting to retrieve deleted group from the store."); retrievedGroup = GroupService.findGroup(key); assertNull(msg, retrievedGroup); print(CR + "***** LEAVING GroupsTester.testAddAndDeleteGroups() *****" + CR); } public void testAddToALargeGroup() throws Exception { print(CR + "***** ENTERING GroupsTester.testAddToALargeGroup() *****" + CR); int numEntities = 1000; String msg = null; int idx = 0; String[] entityKeys = new String[numEntities]; IEntity[] entities = new IEntity[numEntities]; print("About to create test entities."); for (int i = 0; i < numEntities; i++) { entityKeys[i] = (getRandomString(random, 3) + i); entities[i] = getNewEntity(entityKeys[i]); } print("Created " + numEntities + " entities."); print("Creating new group."); IEntityGroup bigGroup = getNewGroup(); bigGroup.setName("Big Group"); bigGroup.getChildren(); print("Created" + bigGroup + ". Will now add members..."); for (idx = 0; idx < numEntities; idx++) { bigGroup.addChild(entities[idx]); } msg = "Added " + entities.length + "members. Will now update."; print(msg); bigGroup.update(); print("Finished updating."); print("Will un-cache " + bigGroup); msg = "Finding duplicate group."; print(msg); String groupKey = bigGroup.getKey(); IEntityGroup dupBigGroup = GroupService.findGroup(groupKey); assertNotNull(msg, dupBigGroup); int numAdditionalEntities = 10; String[] additionalEntityKeys = new String[numAdditionalEntities]; IEntity[] additionalEntities = new IEntity[numAdditionalEntities]; print("About to create additional entities."); for (int i = 0; i < numAdditionalEntities; i++) { additionalEntityKeys[i] = (getRandomString(random, 3) + i); additionalEntities[i] = getNewEntity(additionalEntityKeys[i]); } print("Created " + numAdditionalEntities + " additional entities."); print("Adding additional entities."); for (idx = 0; idx < numAdditionalEntities; idx++) { dupBigGroup.addChild(additionalEntities[idx]); print("Added " + additionalEntities[idx]); dupBigGroup.update(); } print("Done adding additional entities"); print("Will un-cache " + dupBigGroup); msg = "Retrieving duplicate group a 2nd time."; print(msg); dupBigGroup = GroupService.findGroup(groupKey); assertNotNull(msg, dupBigGroup); msg = "Getting members from duplicate group."; print(msg); msg = "Done retrieving members. Will now count members."; print(msg); int numMembers = dupBigGroup.getChildren().size(); assertEquals(msg, numMembers, (numEntities + numAdditionalEntities)); print(CR + "***** LEAVING GroupsTester.testAddToALargeGroup() *****" + CR); } public void testPagsContains() throws Exception { print(CR + "***** ENTERING GroupsTester.testPagsContains() *****" + CR); String message = null; boolean result = false; // We will rely on the groups defined in the sample configuration. print("Attempting to retrieve PAGS groups."); IEntityGroup pagsRoot = GroupService.findGroup("pags.0"); IEntityGroup pagsUsers = GroupService.findGroup("pags.1"); IEntityGroup pagsDs = GroupService.findGroup("pags.3"); assertNotNull(pagsRoot); assertNotNull(pagsUsers); assertNotNull(pagsDs); print("Found PAGS groups."); message = "PAGS groups should contain no entity members"; assertTrue(message, pagsUsers.getChildren().size() == 0); assertTrue(message, pagsDs.getChildren().size() == 0); // Entities existing in UP_PERSON_DIR IEntity demo = GroupService.getEntity("demo", IPerson.class); IEntity admin = GroupService.getEntity("admin", IPerson.class); IEntity staff = GroupService.getEntity("staff", IPerson.class); // Entity not existing in UP_PERSON_DIR IEntity testUser = GroupService.getEntity("test", IPerson.class); message = "pags.1 (users) should contain all entities in UP_PERSON_DIR."; result = pagsUsers.contains(demo); assertTrue(message, result); result = pagsUsers.contains(admin); assertTrue(message, result); result = pagsUsers.contains(staff); assertTrue(message, result); message = "pags.1 (users) should not contain test entity."; result = pagsUsers.contains(testUser); assertTrue(message, !result); message = "pags.0 (root) should deepContain all entities in UP_PERSON_DIR."; result = pagsRoot.deepContains(demo); assertTrue(message, result); message = "pags.0 (users) should not deepContain test entity."; result = pagsRoot.deepContains(testUser); assertTrue(message, !result); print(CR + "***** LEAVING GroupsTester.testPagsContains() *****" + CR); } public void testAddAndDeleteMembers() throws Exception { print(CR + "***** ENTERING GroupsTester.testAddAndDeleteMembers() *****" + CR); String msg = null; Class type = TEST_ENTITY_CLASS; int totNumGroups = 3; int totNumEntities = 5; IEntityGroup[] groups = new IEntityGroup[totNumGroups]; IEntity[] entities = new IEntity[totNumEntities]; IGroupMember[] groupMembers = null; Iterator itr = null; ArrayList list = null; int idx = 0; msg = "Creating " + totNumGroups + " new groups."; print(msg); for (idx = 0; idx < totNumGroups; idx++) { groups[idx] = getNewGroup(); assertNotNull(msg, groups[idx]); } IEntityGroup rootGroup = groups[0]; IEntityGroup childGroup = groups[1]; msg = "Adding " + (totNumGroups - 1) + " to root group."; print(msg); for (idx = 1; idx < totNumGroups; idx++) { rootGroup.addChild(groups[idx]); } rootGroup.update(); // in case members not cached. msg = "Retrieving members from root group."; print(msg); list = new ArrayList(rootGroup.getChildren()); assertEquals(msg, (totNumGroups - 1), list.size()); msg = "Adding " + (totNumEntities - 2) + " to root group."; print(msg); for (idx = 0; idx < (totNumEntities - 2); idx++) { rootGroup.addChild(testEntities[idx]); } rootGroup.update(); // in case members not cached. msg = "Retrieving members from root group."; print(msg); list = new ArrayList(); for (itr = rootGroup.getChildren().iterator(); itr.hasNext(); ) { list.add(itr.next()); } assertEquals(msg, (totNumGroups - 1 + totNumEntities - 2), list.size()); msg = "Adding 2 entities to child group."; print(msg); childGroup.addChild(testEntities[totNumEntities - 1]); childGroup.addChild(testEntities[totNumEntities]); childGroup.update(); // in case members not cached. msg = "Retrieving ALL members from root group."; print(msg); list = new ArrayList(rootGroup.getDescendants()); assertEquals(msg, (totNumGroups - 1 + totNumEntities), list.size()); msg = "Deleting child group from root group."; print(msg); rootGroup.removeChild(childGroup); rootGroup.update(); // in case members not cached. msg = "Retrieving ALL members from root group."; print(msg); list = new ArrayList(rootGroup.getDescendants()); assertEquals(msg, (totNumGroups - 2 + totNumEntities - 2), list.size()); print(CR + "***** LEAVING GroupsTester.testAddAndDeleteMembers() *****" + CR); } public void testContains() throws Exception { print(CR + "***** ENTERING GroupsTester.testContains() *****" + CR); String msg = null; Class type = TEST_ENTITY_CLASS; int totNumEntities = 1; IEntityGroup containingGroup, childGroup, dupContainingGroup = null; IEntity[] entities = new IEntity[totNumEntities]; IGroupMember[] groupMembers = null; Iterator itr = null; ArrayList list = null; int idx = 0; boolean testValue = false; msg = "Creating new parent group."; print(msg); containingGroup = getNewGroup(); containingGroup.getChildren(); // cache members assertNotNull(msg, containingGroup); msg = "Creating new child group."; print(msg); childGroup = getNewGroup(); childGroup.getChildren(); // cache members assertNotNull(msg, childGroup); msg = "Creating " + totNumEntities + " new entities."; print(msg); for (idx = 0; idx < totNumEntities; idx++) { entities[idx] = getNewEntity("E" + idx); } msg = "Adding " + (totNumEntities) + " to containing group."; print(msg); for (idx = 0; idx < totNumEntities; idx++) { containingGroup.addChild(entities[idx]); } msg = "Testing if containing group contains entities."; print(msg); for (idx = 0; idx < totNumEntities; idx++) { testValue = containingGroup.contains(entities[idx]); assertTrue(msg, testValue); } msg = "Adding child group to containing group."; print(msg); containingGroup.addChild(childGroup); msg = "Testing if containing group contains child group."; print(msg); testValue = containingGroup.contains(childGroup); assertTrue(msg, testValue); msg = "Updating containing group."; print(msg); containingGroup.update(); msg = "Getting duplicate containing group."; print(msg); dupContainingGroup = findGroup(containingGroup.getKey()); assertNotNull(msg, dupContainingGroup); msg = "Testing if RETRIEVED containing group contains entities."; print(msg); for (idx = 0; idx < totNumEntities; idx++) { testValue = dupContainingGroup.contains(entities[idx]); assertTrue(msg, testValue); } msg = "Testing if RETRIEVED containing group contains child group."; print(msg); testValue = dupContainingGroup.contains(childGroup); assertTrue(msg, testValue); msg = "Deleting containing group from db."; print(msg); containingGroup.delete(); print(CR + "***** LEAVING GroupsTester.testContains() *****" + CR); } public void testDeleteChildGroup() throws Exception { print(CR + "***** ENTERING GroupsTester.testDeleteChildGroup() *****" + CR); String msg = null; Class type = TEST_ENTITY_CLASS; int totNumGroups = 3; int totNumEntities = 5; IEntityGroup[] groups = new IEntityGroup[totNumGroups]; IEntity[] entities = new IEntity[totNumEntities]; IGroupMember[] groupMembers = null; Iterator itr = null; ArrayList list = null; int idx = 0; Exception e = null; msg = "Creating 3 new groups; 2 parents and 1 child..."; print(msg); for (idx = 0; idx < totNumGroups; idx++) { groups[idx] = getNewGroup(); assertNotNull(msg, groups[idx]); } IEntityGroup child = groups[0]; msg = "Adding child to " + (totNumGroups - 1) + " parent groups."; print(msg); for (idx = 1; idx < totNumGroups; idx++) { groups[idx].addChild(child); groups[idx].update(); } msg = "Retrieving containing groups from child."; print(msg); list = new ArrayList(child.getParentGroups()); assertEquals(msg, (totNumGroups - 1), list.size()); msg = "Adding " + (totNumEntities) + " to child group."; print(msg); for (idx = 0; idx < (totNumEntities); idx++) { child.addChild(testEntities[idx]); } msg = "Retrieving members from child group."; print(msg); list = new ArrayList(child.getChildren()); assertEquals(msg, (totNumEntities), list.size()); msg = "Updating child."; print(msg); child.update(); msg = "Will now lock one of the parent groups. (Delete of child should fail.)"; print(msg); ILockableEntityGroup lockedParent = findLockableGroup(groups[1].getKey()); assertNotNull(msg, lockedParent); assertTrue(msg, lockedParent.getLock().isValid()); msg = "Deleting child. (Should FAIL)."; print(msg); ILockableEntityGroup legDelete = findLockableGroup(child.getKey()); try { legDelete.delete(); } catch (GroupsException ge) { e = ge; } assertNotNull(msg, e); msg = "Will now UN-lock the parent group."; print(msg); lockedParent.getLock().release(); assertTrue(msg, !lockedParent.getLock().isValid()); msg = "Deleting child. (Should SUCCEED)."; print(msg); ILockableEntityGroup legDeleteDup = findLockableGroup(child.getKey()); legDeleteDup.delete(); msg = "Retrieving members from parent groups (should be EMPTY)."; print(msg); for (idx = 1; idx < totNumGroups; idx++) { String groupKey = groups[idx].getKey(); IEntityGroup g = findGroup(groupKey); list = new ArrayList(g.getChildren()); assertEquals(msg, 0, list.size()); } print(CR + "***** LEAVING GroupsTester.testDeleteChildGroup() *****" + CR); } public void testGroupMemberUpdate() throws Exception { print(CR + "***** ENTERING GroupsTester.testGroupMemberUpdate() *****" + CR); String msg = null; Iterator itr; Collection list; int idx = 0; Exception e = null; int numAddedEntities = 10; int numDeletedEntities = 5; print("Creating 2 new groups."); IEntityGroup parent = getNewGroup(); parent.setName("parent"); parent.setCreatorID("de3"); String parentKey = parent.getKey(); IEntityGroup child = getNewGroup(); child.setName("child"); child.setCreatorID("de3"); String childKey = child.getKey(); print("Adding " + child + " to " + parent); parent.addChild(child); print("Adding " + numAddedEntities + " members to " + child); for (idx = 0; idx < numAddedEntities; idx++) { child.addChild(testEntities[idx]); } print("Now updating " + parent + " and " + child); child.update(); parent.update(); msg = "Retrieving members from " + child; // child should have numAddedEntities group members. print(msg); list = getGroupMembers(child); assertEquals(msg, (numAddedEntities), list.size()); msg = "Retrieving members from " + parent; // parent should have numAddedEntities + 1 group members. print(msg); list = getAllGroupMembers(parent); assertEquals(msg, (numAddedEntities + 1), list.size()); msg = "Retrieving " + parent + " and " + child + " from db."; print(msg); IEntityGroup retrievedParent = GroupService.findGroup(parentKey); IEntityGroup retrievedChild = GroupService.findGroup(childKey); assertEquals(msg, parent, retrievedParent); assertEquals(msg, child, retrievedChild); // retrievedChild should have numAddedEntities group members. msg = "Retrieving members from " + retrievedChild; print(msg); list = getAllGroupMembers(retrievedChild); assertEquals(msg, numAddedEntities, list.size()); // retrievedParent should have numAddedEntities + 1 group members. msg = "Retrieving members from " + retrievedParent; print(msg); list = getAllGroupMembers(retrievedParent); assertEquals(msg, (numAddedEntities + 1), list.size()); print("Deleting " + numDeletedEntities + " members from " + retrievedChild); for (idx = 0; idx < numDeletedEntities; idx++) { retrievedChild.removeChild(testEntities[idx]); } // retrievedChild should have (numAddedEntities - numDeletedEntities) members. msg = "Retrieving members from " + retrievedChild; print(msg); list = getAllGroupMembers(retrievedChild); assertEquals(msg, (numAddedEntities - numDeletedEntities), list.size()); msg = "Adding back one member to " + retrievedChild; print(msg); retrievedChild.addChild(testEntities[0]); // retrievedChild should have (numAddedEntities - numDeletedEntities + 1) members. msg = "Retrieving members from " + retrievedChild; print(msg); list = getAllGroupMembers(retrievedChild); assertEquals(msg, (numAddedEntities - numDeletedEntities + 1), list.size()); int numChildMembers = list.size(); print("Now updating " + retrievedChild); retrievedChild.update(); msg = "Re-Retrieving " + retrievedChild + " from db."; print(msg); IEntityGroup reRetrievedChild = GroupService.findGroup(childKey); assertEquals(msg, retrievedChild, reRetrievedChild); // re-RetrievedChild should have (numAddedEntities - numDeletedEntities + 1) members. msg = "Retrieving members from " + reRetrievedChild; print(msg); list = getAllGroupMembers(reRetrievedChild); assertEquals(msg, numChildMembers, list.size()); // Remove parent and child groups from db. msg = "Deleting " + retrievedParent + " and " + reRetrievedChild + " from db."; print(msg); retrievedParent.delete(); reRetrievedChild.delete(); IEntityGroup deletedParent = GroupService.findGroup(parentKey); IEntityGroup deletedChild = GroupService.findGroup(childKey); assertNull(msg, deletedParent); assertNull(msg, deletedChild); print(CR + "***** LEAVING GroupsTester.testGroupMemberUpdate() *****" + CR); } public void testGroupMemberValidation() throws Exception { print(CR + "***** ENTERING GroupsTester.testGroupMemberValidation() *****" + CR); String msg = null; Iterator itr; Collection list; int idx = 0; Exception e = null; IEntityGroup parent = getNewGroup(); parent.setName("parent"); parent.setCreatorID("de3"); IEntityGroup child = getNewGroup(); child.setName("child"); child.setCreatorID("de3"); IEntityGroup child2 = getNewGroup(); child2.setName("child"); child2.setCreatorID("de3"); IEntity entity1 = getNewEntity("child"); IEntity entity2 = getNewEntity("child"); IEntity ipersonEntity = GroupService.getEntity("00000", IPERSON_CLASS); msg = "Adding " + child + " to " + parent; print(msg); parent.addChild(child); parent.update(); // members not cached. msg = "Retrieving members from " + parent; // parent should have 1 group member. print(msg); list = getGroupMembers(parent); assertEquals(msg, 1, list.size()); // Test adding a group with a duplicate name. msg = "Adding " + child2 + " to " + parent + " (this is allowed)."; print(msg); try { parent.addChild(child2); parent.update(); // members not cached. } catch (GroupsException ge) { e = ge; } assertNull(msg, e); msg = "Retrieving members from " + parent; // parent should now have 2 group members. print(msg); list = getGroupMembers(parent); assertEquals(msg, 2, list.size()); // Test adding an ENTITY with the same name as a member GROUP. msg = "Adding entity w/same name as child group to " + parent; print(msg); parent.addChild(entity1); parent.update(); // members not cached. msg = "Retrieving members from " + parent; // parent should now have 3 group members. print(msg); list = getGroupMembers(parent); assertEquals(msg, 3, list.size()); // Test adding a group member with a duplicate key. msg = "Adding another entity w/same key as child group to " + parent + " (noop)."; print(msg); try { parent.addChild(entity2); parent.update(); // members not cached. e = null; } catch (GroupsException ge) { e = ge; } assertNull(msg, e); msg = "Retrieving members from " + parent; // parent should still have 3 group members. print(msg); list = getGroupMembers(parent); assertEquals(msg, 3, list.size()); // Test adding a group member with a different type: msg = "Adding an entity of different type to " + parent; print(msg); try { parent.addChild(ipersonEntity); parent.update(); // members not cached. e = null; } catch (GroupsException ge) { e = ge; } assertNotNull(msg, e); msg = "Retrieving members from " + parent; // parent should still have 3 group members. print(msg); list = getGroupMembers(parent); assertEquals(msg, 3, list.size()); // Test adding a circular reference. try { child.addChild(parent); child.update(); // members not cached. e = null; } catch (GroupsException ge) { e = ge; } assertNotNull(msg, e); msg = "Retrieving members from " + child; // child should have 0 members. print(msg); list = getGroupMembers(child); assertEquals(msg, 0, list.size()); print(CR + "***** LEAVING GroupsTester.testGroupMemberValidation() *****" + CR); } public void testRetrieveParentGroups() throws Exception { print(CR + "***** ENTERING GroupsTester.testRetrieveParentGroups() *****" + CR); String msg = null; int numAllGroups = 10; int numContainingGroups = 8; IEntityGroup[] allGroups = new IEntityGroup[numAllGroups]; IEntity testEntity = testEntities[0]; Iterator it = null; Collection list = null; int idx = 0; msg = "Creating " + numAllGroups + " new groups..."; print(msg); for (idx = 0; idx < numAllGroups; idx++) { allGroups[idx] = getNewGroup(); assertNotNull(msg, allGroups[idx]); allGroups[idx].setName("Parent Group " + idx); allGroups[idx].setCreatorID("de3"); allGroups[idx].update(); print("Group " + allGroups[idx].getName() + " created."); } msg = numAllGroups + " new groups created"; print(msg); msg = "Adding " + testEntity + " to " + numContainingGroups + " containing groups."; print(msg); for (idx = 0; idx < numContainingGroups; idx++) { allGroups[idx].addChild(testEntity); allGroups[idx].update(); } msg = "Getting containing groups for " + testEntity; print(msg); list = new ArrayList(); for (it = testEntity.getParentGroups().iterator(); it.hasNext(); ) { list.add(it.next()); } assertEquals(msg, numContainingGroups, list.size()); msg = "Adding parents to the immediate containing groups."; print(msg); for (idx = numContainingGroups; idx < numAllGroups; idx++) { IEntityGroup parent = allGroups[idx]; IEntityGroup child = allGroups[idx - 1]; msg = "Adding " + child + " to " + parent; print(msg); parent.addChild(child); parent.update(); } msg = "Getting ALL containing groups for " + testEntity; print(msg); list = new ArrayList(testEntity.getAncestorGroups()); assertEquals(msg, numAllGroups, list.size()); IEntity duplicateTestEntity = GroupService.getEntity(testEntity.getKey(), testEntity.getType()); msg = "Getting ALL containing groups for DUPLICATE entity:" + testEntity; print(msg); list = new ArrayList(duplicateTestEntity.getAncestorGroups()); assertEquals(msg, numAllGroups, list.size()); print(CR + "***** LEAVING GroupsTester.testRetrieveParentGroups() *****" + CR); } public void testUpdateLockableGroups() throws Exception { print(CR + "***** ENTERING GroupsTester.testUpdateLockableGroups() *****" + CR); String msg = null; Class type = TEST_ENTITY_CLASS; int totNumGroups = 3; int totNumEntities = 5; IEntityGroup[] groups = new IEntityGroup[totNumGroups]; IEntity[] entities = new IEntity[totNumEntities]; IGroupMember[] groupMembers = null; Iterator itr = null; ArrayList list = null; int idx = 0; boolean testValue = false; Exception e = null; msg = "Creating " + totNumGroups + " new groups."; print(msg); for (idx = 0; idx < totNumGroups; idx++) { groups[idx] = getNewGroup(); groups[idx].update(); assertNotNull(msg, groups[idx]); groups[idx].update(); } msg = "Getting group keys."; print(msg); String[] groupKeys = new String[totNumGroups]; for (idx = 0; idx < totNumGroups; idx++) { groupKeys[idx] = groups[idx].getKey(); } msg = "Retrieving lockable group for key " + groupKeys[0]; print(msg); ILockableEntityGroup lockableGroup1 = findLockableGroup(groupKeys[0]); testValue = lockableGroup1.getLock().isValid(); assertTrue(msg, testValue); msg = "Retrieving a duplicate lockable group for key " + groupKeys[0] + " (should FAIL)"; print(msg); try { ILockableEntityGroup lockableGroup2 = findLockableGroup(groupKeys[0]); } catch (GroupsException ge) { e = ge; } assertNotNull(msg, e); e = null; msg = "Checking lock of first group"; print(msg); testValue = lockableGroup1.getLock().isValid(); assertTrue(msg, testValue); String oldName = lockableGroup1.getName(); String newName = "NEW GROUP NAME"; msg = "Update name of lockable group but do not commit."; print(msg); lockableGroup1.setName(newName); assertEquals(msg, newName, lockableGroup1.getName()); msg = "Checking lock of first group"; print(msg); testValue = lockableGroup1.getLock().isValid(); assertTrue(msg, testValue); msg = "Retrieving duplicate group from service; change should NOT be visible."; print(msg); IEntityGroup nonLockableGroup = findGroup(groupKeys[0]); assertEquals(msg, oldName, nonLockableGroup.getName()); msg = "Checking lock of first group"; print(msg); testValue = lockableGroup1.getLock().isValid(); assertTrue(msg, testValue); msg = "Committing change to lockable group"; print(msg); lockableGroup1.update(); testValue = lockableGroup1.getLock().isValid(); assertTrue(msg, !testValue); msg = "Retrieving duplicate group from service; change should be visible now."; print(msg); nonLockableGroup = findGroup(groupKeys[0]); assertEquals(msg, newName, nonLockableGroup.getName()); msg = "Attempting to delete old version of group " + groupKeys[0] + " (should FAIL.)"; print(msg); try { lockableGroup1.delete(); } catch (GroupsException ge) { e = ge; } assertNotNull(msg, e); e = null; msg = "Attempting to delete NEW version of group " + groupKeys[0]; print(msg); ILockableEntityGroup lockableGroup3 = findLockableGroup(groupKeys[0]); lockableGroup3.delete(); nonLockableGroup = findGroup(groupKeys[0]); assertNull(msg, nonLockableGroup); print(CR + "***** LEAVING GroupsTester.testUpdateLockableGroups() *****" + CR); } public void testUpdateLockableGroupsWithRenewableLock() throws Exception { print( CR + "***** ENTERING GroupsTester.testUpdateLockableGroupsWithRenewableLock() *****" + CR); String msg = null; Class type = TEST_ENTITY_CLASS; IEntityGroup group = null; boolean testValue = false; Exception e = null; String groupKey = null; msg = "Creating new group."; print(msg); group = getNewGroup(); group.update(); assertNotNull(msg, group); msg = "Getting group key."; print(msg); groupKey = group.getKey(); msg = "Retrieving lockable group for key " + groupKey; print(msg); ILockableEntityGroup lockableGroup = findLockableGroup(groupKey); assertNotNull(msg, lockableGroup); msg = "Checking lock of first group"; print(msg); testValue = lockableGroup.getLock().isValid(); assertTrue(msg, testValue); String oldName = lockableGroup.getName(); String newName = "NEW GROUP NAME"; msg = "Updating name of lockable group but not committing."; print(msg); lockableGroup.setName(newName); assertEquals(msg, newName, lockableGroup.getName()); msg = "Checking lock of first group"; print(msg); testValue = lockableGroup.getLock().isValid(); assertTrue(msg, testValue); msg = "Committing change to lockable group and renewing lock."; print(msg); lockableGroup.updateAndRenewLock(); testValue = lockableGroup.getLock().isValid(); assertTrue(msg, testValue); msg = "Retrieving duplicate group from service; change should be visible now."; print(msg); IEntityGroup nonLockableGroup = findGroup(groupKey); assertEquals(msg, newName, nonLockableGroup.getName()); msg = "Update name of lockable group again."; print(msg); lockableGroup.setName(oldName); assertEquals(msg, oldName, lockableGroup.getName()); msg = "Committing change to lockable group and renewing lock."; print(msg); lockableGroup.updateAndRenewLock(); testValue = lockableGroup.getLock().isValid(); assertTrue(msg, testValue); msg = "Attempting to delete lockable group " + groupKey; print(msg); lockableGroup.delete(); nonLockableGroup = findGroup(groupKey); assertNull(msg, nonLockableGroup); print( CR + "***** LEAVING GroupsTester.testUpdateLockableGroupsWithRenewableLock() *****" + CR); } public void testUpdateMembersVisibility() throws Exception { print(CR + "***** ENTERING GroupsTester.testUpdateMembersVisibility() *****" + CR); String msg = null; Class type = TEST_ENTITY_CLASS; int totNumGroups = 3; int totNumEntities = 5; IEntityGroup[] groups = new IEntityGroup[totNumGroups]; IEntity[] entities = new IEntity[totNumEntities]; IGroupMember[] groupMembers = null; Iterator itr = null; ArrayList list = null; int idx = 0; boolean testValue = false; msg = "Creating " + totNumGroups + " new groups."; print(msg); for (idx = 0; idx < totNumGroups; idx++) { groups[idx] = getNewGroup(); groups[idx].getChildren(); // cache members from now on. assertNotNull(msg, groups[idx]); } IEntityGroup rootGroup = groups[0]; IEntityGroup childGroup = groups[1]; msg = "Adding " + (totNumGroups - 1) + " to root group."; print(msg); for (idx = 1; idx < totNumGroups; idx++) { rootGroup.addChild(groups[idx]); } msg = "Retrieving members from root group."; print(msg); list = new ArrayList(rootGroup.getChildren()); assertEquals(msg, (totNumGroups - 1), list.size()); msg = "Adding " + (totNumEntities - 2) + " to root group."; print(msg); for (idx = 0; idx < (totNumEntities - 2); idx++) { rootGroup.addChild(testEntities[idx]); } msg = "Retrieving members from root group."; print(msg); list = new ArrayList(rootGroup.getChildren()); assertEquals(msg, (totNumGroups - 1 + totNumEntities - 2), list.size()); msg = "Adding 2 entities to child group."; print(msg); childGroup.addChild(testEntities[totNumEntities - 1]); childGroup.addChild(testEntities[totNumEntities]); msg = "Retrieving ALL members from root group."; print(msg); list = new ArrayList(rootGroup.getDescendants()); assertEquals(msg, (totNumGroups - 1 + totNumEntities), list.size()); // At this point, the child group members should not yet be aware of their parents. msg = "Checking child groups for parents (should be none)."; print(msg); list = new ArrayList(); for (idx = 1; idx < totNumGroups; idx++) { list.addAll(groups[idx].getParentGroups()); assertEquals(msg, 0, list.size()); } testValue = testEntities[0].isMemberOf(rootGroup); assertEquals(msg, false, testValue); // Update the parent group. Its children should now be aware of it. msg = "Updating parent group."; print(msg); rootGroup.update(); msg = "Checking child entity for membership in parent."; print(msg); testValue = testEntities[0].isMemberOf(rootGroup); assertEquals(msg, true, testValue); // Child group not yet updated. Its child should still be unaware of it. msg = "Checking child entity for membership in child group."; print(msg); testValue = testEntities[totNumEntities].isMemberOf(childGroup); assertEquals(msg, false, testValue); // Update the child group. Its children should now be aware of it. msg = "Updating child group."; print(msg); childGroup.update(); msg = "Checking child entity for membership in child group."; print(msg); testValue = testEntities[totNumEntities].isMemberOf(childGroup); assertEquals(msg, true, testValue); msg = "Getting child entity thru the service (should be cached copy)."; print(msg); EntityIdentifier entID = testEntities[totNumEntities].getUnderlyingEntityIdentifier(); IGroupMember ent = GroupService.getGroupMember(entID); msg = "Checking child entity for membership in child group."; print(msg); testValue = ent.isMemberOf(childGroup); assertEquals(msg, true, testValue); // Child entity should now be aware of both of its parents. msg = "Checking child entity for ALL containing groups."; print(msg); list = new ArrayList(ent.getAncestorGroups()); assertEquals(msg, 2, list.size()); print(CR + "***** LEAVING GroupsTester.testUpdateMembersVisibility() *****" + CR); } public void testMixLockableAndNonLockableGroups() throws Exception { print(CR + "***** ENTERING GroupsTester.testMixLockableAndNonLockableGroups() *****" + CR); String msg = null; Class type = TEST_ENTITY_CLASS; int totNumGroups = 3; IEntityGroup[] groups = new IEntityGroup[totNumGroups]; boolean testValue = false; Exception e = null; int idx = 0; msg = "Creating " + totNumGroups + " new groups."; print(msg); for (idx = 0; idx < totNumGroups; idx++) { groups[idx] = getNewGroup(); groups[idx].update(); assertNotNull(msg, groups[idx]); groups[idx].update(); } msg = "Getting group keys."; print(msg); String[] groupKeys = new String[totNumGroups]; for (idx = 0; idx < totNumGroups; idx++) { groupKeys[idx] = groups[idx].getKey(); } msg = "Retrieving nonLockable group " + groupKeys[0]; print(msg); IEntityGroup group1 = findGroup(groupKeys[0]); assertNotNull(msg, group1); msg = "Retrieving lockable group for key " + groupKeys[0]; print(msg); ILockableEntityGroup lockableGroup = findLockableGroup(groupKeys[0]); testValue = lockableGroup.getLock().isValid(); assertTrue(msg, testValue); msg = "Updating lockable group."; print(msg); String oldName = lockableGroup.getName(); String newName = "NEW GROUP NAME"; print(msg); lockableGroup.setName(newName); lockableGroup.update(); msg = "Retrieving a second nonLockable group for " + groupKeys[0]; print(msg); IEntityGroup group2 = findGroup(groupKeys[0]); assertNotNull(msg, group2); assertEquals(msg, newName, group2.getName()); msg = "Updating second nonLockable group."; print(msg); group2.setName(oldName); group2.update(); msg = "Retrieving a second lockable group for key " + groupKeys[0]; print(msg); ILockableEntityGroup lockableGroup2 = findLockableGroup(groupKeys[0]); testValue = lockableGroup2.getLock().isValid(); assertTrue(msg, testValue); msg = "Updating second lockable group."; print(msg); lockableGroup2.setName(newName); lockableGroup2.update(); print(CR + "***** LEAVING GroupsTester.testMixLockableAndNonLockableGroups() *****" + CR); } public void testConcurrentAccess() throws Exception { print(CR + "***** ENTERING GroupsTester.testConcurrentAccess() *****" + CR); String msg = null; Class type = TEST_ENTITY_CLASS; int totNumGroups = 3; int numContainingGroups = totNumGroups - 1; IEntityGroup[] groups = new IEntityGroup[totNumGroups]; int idx = 0; int numReadTests = 50; int numThreads = 10; msg = "Creating " + totNumGroups + " new groups."; print(msg); for (idx = 0; idx < totNumGroups; idx++) { groups[idx] = getNewGroup(); groups[idx].update(); assertNotNull(msg, groups[idx]); groups[idx].update(); } IEntityGroup child = groups[0]; msg = "Adding parents to child group " + child.getName(); print(msg); for (idx = 1; idx < totNumGroups; idx++) { IEntityGroup parent = groups[idx]; parent.addChild(child); groups[idx].update(); } print("Starting testing Threads."); Thread[] testers = new Thread[numThreads]; for (idx = 0; idx < numThreads; idx++) { String id = "" + idx; GroupsReadTester grt = new GroupsReadTester(id, child, numReadTests); testers[idx] = new Thread(grt); testers[idx].start(); } msg = "Adding members to " + child; print(msg); for (idx = 0; idx < numTestEntities; idx++) { IEntity childEntity = testEntities[idx]; child.addChild(childEntity); if (idx % 10 == 0) // update once for every 10 adds { child.update(); } assertTrue(msg, child.contains(childEntity)); // print("added entity # " + (idx + 1) + " to " + child); } msg = "Updating " + child; print(msg); child.update(); msg = "Removing members from " + child; print(msg); for (idx = 0; idx < numTestEntities; idx++) { IEntity childEntity = testEntities[idx]; child.removeChild(childEntity); assertTrue(msg, !child.contains(childEntity)); } msg = "Updating " + child; print(msg); child.update(); Thread.sleep(numReadTests * 20); // let them die. print(CR + "***** LEAVING GroupsTester.testConcurrentAccess() *****" + CR); } public void testParseCompoundKeys() throws Exception { print(CR + "***** ENTERING GroupsTester.testParseCompoundKeys() *****" + CR); String msg = null; int maxNodes = 5; int idx = 0; String[] keys = new String[maxNodes]; String[] nodes = new String[maxNodes]; String key = null; String sep = GroupServiceConfiguration.getConfiguration().getNodeSeparator(); print("GroupServiceConfiguration node separator: " + sep); print("Creating random node strings."); for (idx = 0; idx < maxNodes; idx++) { nodes[idx] = (getRandomString(random, 3) + idx); } print("Creating keys."); for (idx = 0; idx < maxNodes; idx++) { key = nodes[0]; for (int i = 1; i <= idx; i++) { key = key + sep + nodes[i]; } keys[idx] = key; print("key " + idx + " : " + key); } for (idx = 1; idx < maxNodes; idx++) { CompositeEntityIdentifier cei = null; msg = "Creating CompositeEntityIdentifier for " + keys[idx]; print(msg); cei = new CompositeEntityIdentifier(keys[idx], GROUP_CLASS); assertNotNull(msg, cei); msg = "Testing COMPOUND key of " + cei; assertEquals(msg, keys[idx], cei.getKey()); msg = "Testing LOCAL key of " + cei; assertEquals(msg, nodes[idx], cei.getLocalKey()); msg = "Testing SERVICE NAME of " + cei; assertEquals(msg, idx, cei.getServiceName().size()); } print(CR + "***** LEAVING GroupsTester.testParseCompoundKeys() *****" + CR); } }