001: /*
002: * CoadunationLib: The coaduntion implementation library.
003: * Copyright (C) 2006 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * CoadunationThreadGroupTest.java
020: *
021: * JUnit based test
022: */
023:
024: package com.rift.coad.lib.thread;
025:
026: import java.net.URLClassLoader;
027: import java.net.URL;
028: import junit.framework.*;
029: import java.util.Vector;
030: import java.util.List;
031: import java.util.Date;
032: import java.util.ArrayList;
033: import org.apache.log4j.Logger;
034: import com.rift.coad.lib.security.UserSession;
035: import com.rift.coad.lib.security.user.UserSessionManager;
036: import com.rift.coad.lib.configuration.ConfigurationFactory;
037: import com.rift.coad.lib.configuration.Configuration;
038: import com.rift.coad.lib.security.user.UserStoreManager;
039: import com.rift.coad.lib.security.ThreadsPermissionContainer;
040: import com.rift.coad.lib.security.login.handlers.PasswordInfoHandler;
041: import com.rift.coad.lib.security.SessionManager;
042: import com.rift.coad.lib.security.RoleManager;
043: import com.rift.coad.lib.security.Validator;
044: import com.rift.coad.lib.security.login.LoginManager;
045: import com.rift.coad.lib.thread.CoadunationThread;
046:
047: /**
048: *
049: * @author mincemeat
050: */
051: public class CoadunationThreadGroupTest extends TestCase {
052:
053: /**
054: * The class defintion
055: */
056: public static class TestMonitor {
057: // constants
058: private static final long TIMEOUT = 10000;
059:
060: // static variables
061: private static TestMonitor singleton = null;
062:
063: // private member variables
064: private long count = 0;
065:
066: private TestMonitor() {
067: }
068:
069: public static synchronized TestMonitor getInstance() {
070: if (singleton == null) {
071: singleton = new TestMonitor();
072: }
073: return singleton;
074: }
075:
076: /**
077: * This method will notify any waiting threads that the call landed.
078: */
079: public synchronized void notifyTest() {
080: count++;
081: notify();
082: }
083:
084: /**
085: * Wait for the test to complete.
086: *
087: * @return TRUE if the test succeeded, FALSE if not.
088: * @exception Exception
089: */
090: public synchronized boolean waitForTest() throws Exception {
091: try {
092: long startTime = new Date().getTime();
093: while (count < 6) {
094: wait(TIMEOUT);
095: long currentTime = new Date().getTime();
096: if (count == 6) {
097: return true;
098: } else if ((currentTime - TIMEOUT) >= startTime) {
099: return false;
100: }
101: }
102: return true;
103: } catch (Exception ex) {
104: throw new Exception("Failed to wait for test : "
105: + ex.getMessage(), ex);
106: }
107: }
108: }
109:
110: /**
111: *
112: */
113: public static class SubThread extends CoadunationThread {
114: // the class log variable
115: public static int subThreadTerminateCount = 0;
116: protected Logger log = Logger.getLogger(TestThread.class
117: .getName());
118:
119: // the flag
120: private boolean terminated = false;
121:
122: /**
123: * This object is used to test the threading funcationlity implemented
124: * by the threading group.
125: */
126: public SubThread() throws Exception {
127: }
128:
129: /**
130: * This method replaces the run method in the BasicThread.
131: *
132: * @exception Exception
133: */
134: public void process() throws Exception {
135: boolean notify = false;
136: while (isTerminated() == false) {
137: System.out.println("Message from sub thread : "
138: + this .getId());
139: if (isTerminated() == false) {
140: delay(2000);
141: }
142: if (notify == false) {
143: com.rift.coad.lib.thread.CoadunationThreadGroupTest.TestMonitor
144: .getInstance().notifyTest();
145: notify = true;
146: }
147: }
148: System.out.println("Sub Thread id [" + this .getId()
149: + "] is terminated");
150: subThreadTerminateCount++;
151: }
152:
153: /**
154: * This method will be implemented by child objects to terminate the
155: * processing of this thread.
156: */
157: public synchronized void terminate() {
158: terminated = true;
159: notify();
160: }
161:
162: /**
163: * This method will return true if the terminated flag has been set.
164: *
165: * @return TRUE if terminated flag set, FALSE otherwise
166: */
167: private synchronized boolean isTerminated() {
168: return terminated;
169: }
170:
171: /**
172: * This method will wait for the required delay period.
173: *
174: * @param time The time to wait for.
175: */
176: private synchronized void delay(long time) {
177: try {
178: wait(time);
179: } catch (Exception ex) {
180: // do nothing
181: }
182: }
183: }
184:
185: /**
186: * The test thread class.
187: */
188: public static class TestThread extends BasicThread {
189: // the class log variable
190: protected Logger log = Logger.getLogger(TestThread.class
191: .getName());
192:
193: // the flag
194: private boolean terminated = false;
195:
196: /**
197: * This object is used to test the threading funcationlity implemented
198: * by the threading group.
199: */
200: public TestThread() throws Exception {
201: }
202:
203: /**
204: * This method replaces the run method in the BasicThread.
205: *
206: * @exception Exception
207: */
208: public void process() throws Exception {
209: boolean notify = false;
210: while (isTerminated() == false) {
211: System.out.println("Message from thread : "
212: + this .getId());
213: if (isTerminated() == false) {
214: delay(2000);
215: }
216: if (notify == false) {
217: SubThread subThread = new SubThread();
218: try {
219: subThread.start("test");
220: } catch (Exception ex) {
221: System.out
222: .println("Failed to start the sub thread : "
223: + ex.getMessage());
224: ex.printStackTrace(System.out);
225: }
226: com.rift.coad.lib.thread.CoadunationThreadGroupTest.TestMonitor
227: .getInstance().notifyTest();
228: notify = true;
229: }
230: }
231: System.out.println("Thread id [" + this .getId()
232: + "] is terminated");
233: }
234:
235: /**
236: * This method will be implemented by child objects to terminate the
237: * processing of this thread.
238: */
239: public synchronized void terminate() {
240: terminated = true;
241: notify();
242: }
243:
244: /**
245: * This method will return true if the terminated flag has been set.
246: *
247: * @return TRUE if terminated flag set, FALSE otherwise
248: */
249: private synchronized boolean isTerminated() {
250: return terminated;
251: }
252:
253: /**
254: * This method will wait for the required delay period.
255: *
256: * @param time The time to wait for.
257: */
258: private synchronized void delay(long time) {
259: try {
260: wait(time);
261: } catch (Exception ex) {
262: // do nothing
263: }
264: }
265: }
266:
267: /**
268: * The test thread class.
269: */
270: public static class NoTerminateTestThread extends BasicThread {
271: // the class log variable
272: protected Logger log = Logger
273: .getLogger(NoTerminateTestThread.class.getName());
274:
275: /**
276: * This object is used to test the threading funcationlity implemented
277: * by the threading group.
278: */
279: public NoTerminateTestThread() throws Exception {
280: }
281:
282: /**
283: * This method replaces the run method in the BasicThread.
284: *
285: * @exception Exception
286: */
287: public void process() throws Exception {
288: while (true) {
289: System.out.println("Message from thread : "
290: + this .getId());
291: Thread.sleep(2000);
292: }
293: }
294:
295: /**
296: * This method will be implemented by child objects to terminate the
297: * processing of this thread.
298: */
299: public synchronized void terminate() {
300: // do nothing
301: }
302: }
303:
304: public CoadunationThreadGroupTest(String testName) {
305: super (testName);
306: }
307:
308: protected void setUp() throws Exception {
309: }
310:
311: protected void tearDown() throws Exception {
312: }
313:
314: public static Test suite() {
315: TestSuite suite = new TestSuite(
316: CoadunationThreadGroupTest.class);
317:
318: return suite;
319: }
320:
321: /**
322: * Test of the thread group class com.rift.coad.lib.thread.CoadunationThreadGroup.
323: */
324: public void testThreadGroup() throws Exception {
325: System.out.println("testThreadGroup");
326:
327: // initialize the thread permissions
328: ThreadsPermissionContainer permissions = new ThreadsPermissionContainer();
329: SessionManager.init(permissions);
330: UserStoreManager userStoreManager = new UserStoreManager();
331: UserSessionManager sessionManager = new UserSessionManager(
332: permissions, userStoreManager);
333: LoginManager.init(sessionManager, userStoreManager);
334:
335: // add a user to the session for the current thread
336: RoleManager.getInstance();
337:
338: // the thread group manager
339:
340: // instanciate the thread manager
341: CoadunationThreadGroup threadGroup = new CoadunationThreadGroup(
342: sessionManager, userStoreManager);
343: ClassLoader loader = new URLClassLoader(new URL[0], this
344: .getClass().getClassLoader());
345: Thread.currentThread().setContextClassLoader(loader);
346: ThreadGroupManager.getInstance().initThreadGroup(threadGroup);
347: // start 3 threads
348: threadGroup
349: .startThreads(
350: com.rift.coad.lib.thread.CoadunationThreadGroupTest.TestThread.class,
351: "test", 3);
352:
353: // start 3 threads
354: threadGroup
355: .startThreads(
356: com.rift.coad.lib.thread.CoadunationThreadGroupTest.NoTerminateTestThread.class,
357: "test", 1);
358:
359: if (TestMonitor.getInstance().waitForTest() == false) {
360: fail("Failed to run the test.");
361: return;
362: }
363:
364: // retrieve the thread list
365: List threadList = threadGroup.getThreadInfo();
366: if (threadList.size() != 4) {
367: fail("There should be 4 threads in the group there are ["
368: + threadList.size() + "]");
369: }
370:
371: // loop through the results
372: boolean found = false;
373: for (int i = 0; i < threadList.size(); i++) {
374: ThreadInfo info = (ThreadInfo) threadList.get(i);
375: System.out.println("Class ["
376: + info.getThreadClass().getName() + "] id ["
377: + info.getThreadId() + "] username ["
378: + info.getUser().getName() + "] info ["
379: + info.getInfo() + "]");
380: if (info.getUser().getName().equals("test") == false) {
381: fail("The invalid user [" + info.getUser().getName()
382: + "] id [" + info.getThreadId() + "]");
383: }
384: if (info
385: .getThreadClass()
386: .getName()
387: .equals(
388: com.rift.coad.lib.thread.CoadunationThreadGroupTest.TestThread.class
389: .getName())) {
390: found = true;
391: }
392: }
393:
394: if (found == false) {
395: fail("Failed to find the matching threads");
396: }
397:
398: // create a child thread group
399: CoadunationThreadGroup childThreadGroup = threadGroup
400: .createThreadGroup();
401:
402: // terminate
403: threadGroup.terminate();
404: ThreadGroupManager.getInstance().terminateThreadGroup();
405:
406: if (SubThread.subThreadTerminateCount != 3) {
407: fail("Failed to terminate the sub threads");
408: }
409: }
410: }
|