001: /* Copyright 2002 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.concurrency.locking;
007:
008: import junit.framework.TestCase;
009: import junit.framework.TestSuite;
010:
011: import org.jasig.portal.concurrency.IEntityLock;
012: import org.jasig.portal.concurrency.IEntityLockService;
013: import org.jasig.portal.concurrency.LockingException;
014: import org.jasig.portal.properties.PropertiesManager;
015: import org.jasig.portal.services.EntityLockService;
016:
017: /**
018: * Tests the entity lock framework.
019: * @author: Dan Ellentuck
020: */
021: public class EntityLockTest extends TestCase {
022: private static Class GROUP_CLASS;
023: private static Class IPERSON_CLASS;
024: private IEntityLock[] testLocks;
025: private IEntityLockStore lockStore;
026: private int numUnexpiredIEntityGroupLocksInStore = 0;
027: private int numExpiredLocks = 0;
028: private int numUnexpiredIPersonLocksInStore = 0;
029: private int numIPersonLocksInStoreForTestId = 0;
030: private String[] testKeys = { "101", "102", "9999999", "12345" };
031: private String[] testIds = { "de3", "df7", "av317" };
032:
033: /**
034: * EntityLockTester constructor comment.
035: */
036: public EntityLockTest(String name) {
037: super (name);
038: }
039:
040: /**
041: * @return org.jasig.portal.concurrency.locking.IEntityLockStore
042: */
043: private IEntityLockStore getLockStore() {
044: return lockStore;
045: }
046:
047: /**
048: * @return org.jasig.portal.groups.IEntityLockService
049: */
050: private IEntityLockService getService() throws LockingException {
051: return ReferenceEntityLockService.singleton();
052: }
053:
054: /**
055: * Starts the application.
056: * @param args an array of command-line arguments
057: */
058: public static void main(java.lang.String[] args) throws Exception {
059: String[] mainArgs = { "org.jasig.portal.concurrency.locking.EntityLockTester" };
060: print("START TESTING LOCK STORE");
061: printBlankLine();
062: junit.swingui.TestRunner.main(mainArgs);
063: printBlankLine();
064: print("END TESTING LOCK STORE");
065:
066: }
067:
068: /**
069: */
070: private static void print(IEntityLock[] locks) {
071: for (int i = 0; i < locks.length; i++) {
072: print("(" + (i + 1) + ") " + locks[i]);
073: }
074: print(" Total: " + locks.length);
075: }
076:
077: /**
078: * @param msg java.lang.String
079: */
080: private static void print(String msg) {
081: java.sql.Timestamp ts = new java.sql.Timestamp(System
082: .currentTimeMillis());
083: System.out.println(ts + " : " + msg);
084: }
085:
086: /**
087: */
088: private static void printBlankLine() {
089: System.out.println("");
090: }
091:
092: /**
093: */
094: protected void setUp() {
095: try {
096: if (GROUP_CLASS == null) {
097: GROUP_CLASS = Class
098: .forName("org.jasig.portal.groups.IEntityGroup");
099: }
100: if (IPERSON_CLASS == null) {
101: IPERSON_CLASS = Class
102: .forName("org.jasig.portal.security.IPerson");
103: }
104:
105: try {
106: boolean multiServer = PropertiesManager
107: .getPropertyAsBoolean(
108: "org.jasig.portal.concurrency.multiServer",
109: false);
110:
111: lockStore = (multiServer) ? RDBMEntityLockStore
112: .singleton() : MemoryEntityLockStore
113: .singleton();
114: } catch (Exception e) {
115: System.out
116: .println("EntityLockTester:setUp(): Failed to instantiate entity lock store. "
117: + e);
118: }
119:
120: lockStore.deleteAll();
121:
122: java.util.Date earlier = new java.util.Date(System
123: .currentTimeMillis() - 1000); // - 1 second
124: java.util.Date later = new java.util.Date(System
125: .currentTimeMillis() + 300000); // + 5 minutes
126: testLocks = new IEntityLock[5];
127: testLocks[0] = new EntityLockImpl(GROUP_CLASS, testKeys[0],
128: 0, later, testIds[0]);
129: testLocks[1] = new EntityLockImpl(GROUP_CLASS, testKeys[1],
130: 0, later, testIds[0]);
131: testLocks[2] = new EntityLockImpl(IPERSON_CLASS,
132: testKeys[0], 0, earlier, testIds[0]);
133: testLocks[3] = new EntityLockImpl(IPERSON_CLASS,
134: testKeys[1], 1, later, testIds[0]);
135: testLocks[4] = new EntityLockImpl(IPERSON_CLASS,
136: testKeys[2], 1, later, testIds[1]);
137:
138: print("Adding test locks.");
139: for (int i = 0; i < testLocks.length; i++) {
140: getLockStore().add(testLocks[i]);
141: // print("Added " + testLocks[i]);
142: }
143:
144: numUnexpiredIEntityGroupLocksInStore = 2;
145: numExpiredLocks = 1;
146: numUnexpiredIPersonLocksInStore = 2;
147: numIPersonLocksInStoreForTestId = 1;
148: } catch (Exception ex) {
149: print("EntityLockTester.setUp(): " + ex.getMessage());
150: }
151: }
152:
153: /**
154: * @return junit.framework.Test
155: */
156: public static junit.framework.Test suite() {
157: TestSuite suite = new TestSuite();
158:
159: suite.addTest(new EntityLockTest("testExistsInStore"));
160: suite.addTest(new EntityLockTest("testSelectFromStore"));
161: suite.addTest(new EntityLockTest("testExpirationInStore"));
162: suite.addTest(new EntityLockTest("testStoreUpdate"));
163: suite.addTest(new EntityLockTest("testServiceNewLock"));
164: suite.addTest(new EntityLockTest("testServiceLockRenewal"));
165: suite.addTest(new EntityLockTest("testServiceConvert"));
166: suite.addTest(new EntityLockTest("testService"));
167:
168: // Add more tests here.
169: // NB: Order of tests is not guaranteed.
170:
171: return suite;
172: }
173:
174: /**
175: */
176: protected void tearDown() {
177: try {
178: // delete any remaining test locks.
179: print("Deleting test locks.");
180: for (int i = 0; i < testLocks.length; i++) {
181: getLockStore().delete(testLocks[i]);
182: }
183: } catch (Exception ex) {
184: print("EntityLockTester.tearDown(): " + ex.getMessage());
185: }
186: }
187:
188: /**
189: */
190: public void testExistsInStore() throws Exception {
191: String msg = null;
192: IEntityLock lock = testLocks[4];
193: msg = "Checking if " + lock + " exists in database.";
194: print(msg);
195: boolean exists = getService().existsInStore(lock);
196: assertTrue(msg, exists);
197:
198: // Delete the lock:
199: print("Deleting lock from database.");
200: getLockStore().delete(lock);
201:
202: // does lock exist?
203: msg = "Checking if deleted lock exists in database.";
204: print(msg);
205: exists = getService().existsInStore(lock);
206: assertTrue(msg, !exists);
207:
208: // Add the lock back:
209: print("Adding back the lock just deleted from database.");
210: getLockStore().add(lock);
211:
212: }
213:
214: /**
215: */
216: public void testExpirationInStore() throws Exception {
217: int numLocks = 0;
218: int ctr = 0;
219: String msg = null;
220: IEntityLock[] selectedLocks = null;
221: java.util.Date now = new java.util.Date(System
222: .currentTimeMillis());
223:
224: // select unexpired locks by entity type
225: msg = "Selecting unexpired locks by type.";
226: print(msg);
227: selectedLocks = getLockStore().findUnexpired(now,
228: IPERSON_CLASS, null, null, null);
229: numLocks = selectedLocks.length;
230: assertEquals(numLocks, numUnexpiredIPersonLocksInStore);
231: for (ctr = 0; ctr < numLocks; ctr++) {
232: assertTrue(msg, selectedLocks[ctr].getExpirationTime()
233: .after(now));
234: }
235:
236: // Get rid of the EXPIRED locks.
237: print("Deleting expired locks.");
238: getLockStore().deleteExpired(
239: new java.util.Date(System.currentTimeMillis()));
240:
241: // Select the remaining UNEXPIRED locks.
242: msg = "Selected all remaining locks.";
243: print(msg);
244: selectedLocks = getLockStore().find(null, null, null, null,
245: null);
246:
247: numLocks = selectedLocks.length;
248: msg = "Selected " + numLocks + " unexpired locks";
249: print(msg);
250: assertEquals(msg, testLocks.length - numExpiredLocks, numLocks);
251: for (ctr = 0; ctr < numLocks; ctr++) {
252: assertTrue(msg, selectedLocks[ctr].getExpirationTime()
253: .after(now));
254: }
255:
256: }
257:
258: /**
259: */
260: public void testSelectFromStore() throws Exception {
261: int numLocks = 0;
262: int ctr = 0;
263: IEntityLock[] selectedLocks = null;
264: String msg = null;
265: java.util.Date now = new java.util.Date(System
266: .currentTimeMillis());
267:
268: // select locks by entity type
269: msg = "Selecting locks for Group type.";
270: print(msg);
271: selectedLocks = getLockStore().find(GROUP_CLASS, null, null,
272: null, null);
273: numLocks = selectedLocks.length;
274: assertEquals(numLocks, numUnexpiredIEntityGroupLocksInStore);
275: for (ctr = 0; ctr < numLocks; ctr++) {
276: assertEquals(msg, selectedLocks[ctr].getEntityType(),
277: GROUP_CLASS);
278: }
279:
280: // select locks by entity type and entity key
281: msg = "Selecting locks by type and key.";
282: print(msg);
283: selectedLocks = getLockStore().find(GROUP_CLASS, testKeys[1],
284: null, null, null);
285: numLocks = selectedLocks.length;
286: assertEquals(msg, numLocks, 1);
287: assertEquals(msg, selectedLocks[0].getEntityType(), GROUP_CLASS);
288: assertEquals(msg, selectedLocks[0].getEntityKey(), testKeys[1]);
289:
290: // select locks by entity type, entity key and lock type
291: msg = "Selecting locks by type, key, and lock type";
292: print(msg);
293: selectedLocks = getLockStore().find(IPERSON_CLASS, testKeys[1],
294: new Integer(1), null, null);
295: numLocks = selectedLocks.length;
296: assertEquals(msg, numLocks, 1);
297: assertEquals(msg, selectedLocks[0].getEntityType(),
298: IPERSON_CLASS);
299: assertEquals(msg, selectedLocks[0].getEntityKey(), testKeys[1]);
300: assertEquals(msg, selectedLocks[0].getLockType(), 1);
301:
302: selectedLocks = getLockStore().find(IPERSON_CLASS, testKeys[1],
303: new Integer(0), null, null);
304: numLocks = selectedLocks.length;
305: assertEquals(msg, numLocks, 0);
306:
307: // select locks by entity type and owner
308: msg = "Selecting locks by entity type and owner";
309: String id = testIds[1];
310: print(msg);
311: selectedLocks = getLockStore().find(IPERSON_CLASS, null, null,
312: null, id);
313: numLocks = selectedLocks.length;
314: assertEquals(numLocks, numIPersonLocksInStoreForTestId);
315: for (ctr = 0; ctr < numLocks; ctr++) {
316: assertEquals(msg, selectedLocks[ctr].getEntityType(),
317: IPERSON_CLASS);
318: assertEquals(msg, selectedLocks[ctr].getLockOwner(), id);
319: }
320: }
321:
322: /**
323: */
324: public void testService() throws Exception {
325:
326: String msg = null;
327: IEntityLock readLock1, readLock2, writeLock = null;
328:
329: String key = System.currentTimeMillis() + "";
330:
331: print("Creating first read lock.");
332: readLock1 = EntityLockService.instance().newReadLock(
333: IPERSON_CLASS, key, testIds[0]);
334:
335: print("Creating second read lock (for same entity).");
336: readLock2 = EntityLockService.instance().newReadLock(
337: IPERSON_CLASS, key, testIds[0]);
338:
339: msg = "Attempting to create a write lock for the entity: should fail.";
340: print(msg);
341: try {
342: writeLock = EntityLockService.instance().newWriteLock(
343: IPERSON_CLASS, key, testIds[2]);
344: } catch (LockingException le) {
345: System.out.println("Caught Exception: " + le.getMessage());
346: }
347:
348: assertNull(msg, writeLock);
349:
350: msg = "Releasing read locks: lock should be invalid.";
351: print(msg);
352: readLock1.release();
353: assertTrue(msg, !readLock1.isValid());
354: readLock2.release();
355: assertTrue(msg, !readLock2.isValid());
356:
357: msg = "Attempting to create a write lock for the entity: should succeed.";
358: print(msg);
359: try {
360: writeLock = EntityLockService.instance().newWriteLock(
361: IPERSON_CLASS, key, testIds[2]);
362: } catch (LockingException le) {
363: System.out.println("Caught Exception: " + le.getMessage());
364: }
365:
366: assertTrue(msg, writeLock.isValid());
367: msg = "Releasing write lock: should be invalid.";
368: print(msg);
369: writeLock.release();
370: assertTrue(msg, !writeLock.isValid());
371: }
372:
373: /**
374: */
375: public void testServiceConvert() throws Exception {
376:
377: String msg = null;
378: boolean valid = false;
379: IEntityLockService service = getService();
380: int readSecs = 30;
381: int writeSecs = 45;
382:
383: // Create a READ lock on Group testKeys[3], owned by testIds[0]:
384: print("Creating new READ lock");
385: IEntityLock lock = service.newLock(GROUP_CLASS, testKeys[3],
386: IEntityLockService.READ_LOCK, testIds[0], readSecs);
387: msg = "Testing if new lock is valid";
388: valid = service.isValid(lock);
389: print(msg);
390: assertTrue(msg, valid);
391:
392: // Convert the READ lock to a WRITE lock:
393: print("Converting READ lock to WRITE");
394: service.convert(lock, IEntityLockService.WRITE_LOCK, writeSecs);
395: msg = "Testing if converted lock is still valid";
396: valid = service.isValid(lock);
397: print(msg);
398: assertTrue(msg, valid);
399:
400: // Convert the WRITE lock back to a READ lock:
401: print("Converting WRITE lock to READ");
402: service.convert(lock, IEntityLockService.READ_LOCK, readSecs);
403: msg = "Testing if converted lock is still valid";
404: valid = service.isValid(lock);
405: print(msg);
406: assertTrue(msg, valid);
407:
408: // Now try to create a WRITE lock on the same entity for a different owner.
409: IEntityLock duplicateLock = null;
410: msg = "Attempting to create a duplicate lock; should be null";
411: print(msg);
412:
413: try {
414: duplicateLock = service.newLock(GROUP_CLASS, testKeys[3],
415: IEntityLockService.WRITE_LOCK, testIds[1]);
416: } catch (LockingException le) {
417: print("Caught exception: " + le.getMessage());
418: }
419:
420: assertNull(msg, duplicateLock);
421:
422: }
423:
424: /**
425: */
426: public void testServiceLockRenewal() throws Exception {
427: String msg = null;
428: boolean valid = false;
429: IEntityLockService service = getService();
430:
431: msg = "Attempting to renew an old lock";
432: print(msg);
433: IEntityLock badLock = testLocks[2];
434: msg = "Checking if lock was renewed.";
435: print(msg);
436: try {
437: service.renew(badLock);
438: } catch (Exception ex) {
439: print("Caught Exception: " + ex.getMessage());
440: }
441: assertTrue(msg, !service.isValid(badLock));
442:
443: msg = "Attempting to renew a valid lock";
444: print(msg);
445: IEntityLock goodLock = testLocks[0];
446: msg = "Checking if lock was renewed.";
447: print(msg);
448: try {
449: service.renew(goodLock);
450: } catch (Exception ex) {
451: print("Caught Exception: " + ex.getMessage());
452: }
453: assertTrue(msg, service.isValid(goodLock));
454:
455: }
456:
457: /**
458: */
459: public void testServiceNewLock() throws Exception {
460:
461: String msg = null;
462: boolean valid = false;
463:
464: print("Creating new lock");
465: IEntityLockService service = getService();
466: IEntityLock newLock = service.newLock(GROUP_CLASS, testKeys[3],
467: IEntityLockService.WRITE_LOCK, testIds[0]);
468: msg = "Testing if new lock is valid";
469: valid = getService().existsInStore(newLock);
470: print(msg);
471: assertTrue(msg, valid);
472:
473: print("Releasing new lock");
474: getService().release(newLock);
475: msg = "Testing if new lock is still valid";
476: valid = getService().existsInStore(newLock);
477: print(msg);
478: assertTrue(msg, !valid);
479:
480: }
481:
482: /**
483: */
484: public void testStoreUpdate() throws Exception {
485: long fiveMinutes = 1000 * 60 * 5;
486: long tenMinutes = 1000 * 60 * 10;
487: long now = System.currentTimeMillis();
488: String msg = null;
489:
490: print("Update expiration and lock type of testLocks[1].");
491:
492: java.util.Date newExpiration = new java.util.Date(now
493: + fiveMinutes);
494: int newType = IEntityLockService.WRITE_LOCK;
495:
496: // Copy testLocks[1] to lock1.
497: IEntityLock lock1 = new EntityLockImpl(testLocks[1]
498: .getEntityType(), testLocks[1].getEntityKey(),
499: testLocks[1].getLockType(), testLocks[1]
500: .getExpirationTime(), testLocks[1]
501: .getLockOwner());
502:
503: // Update testLocks[1].
504: getLockStore().update(testLocks[1], newExpiration,
505: new Integer(newType));
506: ((EntityLockImpl) testLocks[1])
507: .setExpirationTime(newExpiration);
508: ((EntityLockImpl) testLocks[1]).setLockType(newType);
509:
510: msg = "Check if the old version (lock1) still exists in store.";
511: print(msg);
512: assertTrue(msg, !getService().existsInStore(lock1));
513:
514: msg = "Check if new version exists in store.";
515: print(msg);
516: IEntityLock lock2 = new EntityLockImpl(lock1.getEntityType(),
517: lock1.getEntityKey(), newType, newExpiration, lock1
518: .getLockOwner());
519: assertTrue(msg, getService().existsInStore(lock2));
520:
521: print("Update only expiration on (updated) lock.");
522: newExpiration = new java.util.Date(now + tenMinutes);
523: getLockStore().update(lock2, newExpiration, null);
524: ((EntityLockImpl) lock2).setExpirationTime(newExpiration);
525:
526: msg = "Check if un-updated lock still exists in store.";
527: print(msg);
528: assertTrue(msg, !getService().existsInStore(testLocks[1]));
529:
530: msg = "Check if the doubly-updated lock exists in store.";
531: print(msg);
532: IEntityLock lock3 = new EntityLockImpl(lock2.getEntityType(),
533: lock2.getEntityKey(), lock2.getLockType(),
534: newExpiration, lock2.getLockOwner());
535: assertTrue(msg, getService().existsInStore(lock3));
536:
537: testLocks[0] = lock3;
538: }
539: }
|