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