001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: AuditTests.java,v 1.7 2007/03/27 21:59:42 mlipp Exp $
021: *
022: * $Log: AuditTests.java,v $
023: * Revision 1.7 2007/03/27 21:59:42 mlipp
024: * Fixed lots of checkstyle warnings.
025: *
026: * Revision 1.6 2007/01/26 14:38:12 drmlipp
027: * Minor updated to process close event delivery.
028: *
029: * Revision 1.5 2006/10/19 13:52:26 drmlipp
030: * Fixed sorting problems.
031: *
032: * Revision 1.4 2006/09/29 12:32:10 drmlipp
033: * Consistently using WfMOpen as projct name now.
034: *
035: * Revision 1.3 2005/04/22 15:11:06 drmlipp
036: * Merged changes from 1.3 branch up to 1.3p15.
037: *
038: * Revision 1.1.1.3.6.4 2005/04/21 12:51:38 drmlipp
039: * Fixed test.
040: *
041: * Revision 1.1.1.3.6.3 2005/04/18 11:11:36 drmlipp
042: * More event handling optimization.
043: *
044: * Revision 1.2 2005/04/08 11:28:06 drmlipp
045: * Merged changes from 1.3 branch up to 1.3p6.
046: *
047: * Revision 1.1.1.3.6.2 2005/04/07 20:47:40 drmlipp
048: * Fixed assertion.
049: *
050: * Revision 1.1.1.3.6.1 2005/04/07 12:13:04 drmlipp
051: * Added event subscriber with filter.
052: *
053: * Revision 1.1.1.3 2004/08/18 15:18:47 drmlipp
054: * Update to 1.2
055: *
056: * Revision 1.27 2004/05/05 09:44:07 lipp
057: * Finished SAX based process creation (no cleanup of old code, yet).
058: *
059: * Revision 1.26 2004/01/27 11:45:33 lipp
060: * Preserve newlines when reading process definitions.
061: *
062: * Revision 1.25 2003/10/21 21:00:45 lipp
063: * Moved EJBClientTest to new junit sub-package.
064: *
065: * Revision 1.24 2003/10/08 11:52:55 huaiyang
066: * make test weblogic compatible.
067: *
068: * Revision 1.23 2003/09/19 13:12:29 lipp
069: * Adapted to closed.completed having a substate.
070: *
071: * Revision 1.22 2003/06/27 09:44:13 lipp
072: * Fixed copyright/license information.
073: *
074: * Revision 1.21 2003/05/12 19:01:03 lipp
075: * Fixed process definition version().
076: *
077: * Revision 1.20 2003/04/26 16:46:55 lipp
078: * Made unittests and systemtests coexist in eclipse.
079: *
080: * Revision 1.19 2003/04/16 19:25:04 lipp
081: * Adapted to jdk 1.4
082: *
083: * Revision 1.18 2003/04/08 15:22:16 lipp
084: * Fixed tests.
085: *
086: * Revision 1.17 2003/03/07 15:09:09 lipp
087: * Minor fixes.
088: *
089: * Revision 1.16 2003/02/27 15:14:40 lipp
090: * Some fixes.
091: *
092: * Revision 1.15 2003/02/25 17:36:05 lipp
093: * Fixed assertion.
094: *
095: * Revision 1.14 2003/02/25 17:08:27 lipp
096: * Reorganized requester implementation.
097: *
098: * Revision 1.13 2003/02/14 10:08:25 lipp
099: * Improved messages.
100: *
101: * Revision 1.12 2003/02/06 16:40:21 lipp
102: * Fixed a state handling bug (must not expose running state for manually
103: * started activity).
104: *
105: * Revision 1.11 2003/02/05 15:57:06 lipp
106: * Replaced DummyRequester with DefaultRequester.
107: *
108: * Revision 1.10 2002/11/21 10:32:06 lipp
109: * Fixed test case.
110: *
111: * Revision 1.9 2002/11/19 15:14:52 lipp
112: * New transition manager.
113: *
114: * Revision 1.8 2002/10/23 07:29:15 lipp
115: * Adapted to state handling changes.
116: *
117: * Revision 1.7 2002/10/17 08:04:58 barzik
118: * initial tests finished
119: *
120: * Revision 1.6 2002/10/11 13:41:54 barzik
121: * adopted to asynch. behaviour of server
122: *
123: * Revision 1.5 2002/10/09 09:40:56 barzik
124: * now using the WorkflowServiceFactory
125: *
126: * Revision 1.4 2002/10/08 12:10:04 barzik
127: * extended to "changeAssignmentAuditEvent" verification test
128: *
129: * Revision 1.3 2002/10/07 12:02:50 barzik
130: * test case "changeActivityResult"
131: *
132: * Revision 1.2 2002/10/02 10:59:09 barzik
133: * extended testcase
134: *
135: * Revision 1.1 2002/10/01 12:45:26 barzik
136: * Initial implementation
137: *
138: *
139: */
140: package process;
141:
142: import java.io.BufferedReader;
143: import java.io.InputStream;
144: import java.io.InputStreamReader;
145:
146: import java.util.ArrayList;
147: import java.util.Collection;
148: import java.util.Collections;
149: import java.util.Comparator;
150: import java.util.Iterator;
151: import java.util.List;
152: import java.util.SortedMap;
153: import java.util.TreeMap;
154:
155: import javax.security.auth.login.LoginException;
156:
157: import de.danet.an.util.junit.EJBClientTest;
158:
159: import de.danet.an.workflow.omgcore.ProcessData;
160: import de.danet.an.workflow.omgcore.WfActivity;
161: import de.danet.an.workflow.omgcore.WfAssignmentAuditEvent;
162: import de.danet.an.workflow.omgcore.WfAuditEvent;
163: import de.danet.an.workflow.omgcore.WfAuditHandler;
164: import de.danet.an.workflow.omgcore.WfCreateProcessAuditEvent;
165: import de.danet.an.workflow.omgcore.WfDataAuditEvent;
166: import de.danet.an.workflow.omgcore.WfExecutionObject;
167: import de.danet.an.workflow.omgcore.WfProcess;
168: import de.danet.an.workflow.omgcore.WfRequester;
169: import de.danet.an.workflow.omgcore.WfStateAuditEvent;
170:
171: import de.danet.an.workflow.api.DefaultRequester;
172: import de.danet.an.workflow.api.EventSubscriber;
173: import de.danet.an.workflow.api.FactoryConfigurationError;
174: import de.danet.an.workflow.api.ProcessClosedAuditEvent;
175: import de.danet.an.workflow.api.ProcessDefinitionDirectory;
176: import de.danet.an.workflow.api.ProcessMgr;
177: import de.danet.an.workflow.api.WorkflowService;
178: import de.danet.an.workflow.api.WorkflowServiceFactory;
179:
180: import common.UTLoginContext;
181: import junit.framework.Test;
182: import junit.framework.TestCase;
183: import junit.framework.TestSuite;
184:
185: /**
186: * Testing audit event handling. This test suite does not make any senseful
187: * things, rather than forcing the creation of several audit events in order
188: * to test that they've been created and written the appropriate database
189: * tables.
190: */
191: public class AuditTests extends TestCase {
192: private static UTLoginContext plc = null;
193: static {
194: try {
195: plc = new UTLoginContext();
196: plc.login();
197: } catch (LoginException e) {
198: throw new IllegalStateException(e.getMessage());
199: }
200: }
201:
202: private static final String OPEN_RUNNING = WfExecutionObject.OpenState.RUNNING
203: .toString();
204: private static final String OPEN_NOT_RUNNING = WfExecutionObject.OpenState.NOT_RUNNING
205: .toString();
206: private static final String CLOSED_COMPLETED = WfExecutionObject.ClosedState.COMPLETED
207: .toString();
208: private static final String CLOSED_ABORTED = WfExecutionObject.ClosedState.ABORTED
209: .toString();
210:
211: private static WorkflowService wfsCache = null;
212:
213: private WorkflowService workflowService() {
214: if (wfsCache == null) {
215: try {
216: WorkflowServiceFactory wfsf = WorkflowServiceFactory
217: .newInstance();
218: wfsCache = wfsf.newWorkflowService();
219: } catch (FactoryConfigurationError e) {
220: throw new IllegalStateException(e.getMessage());
221: }
222: }
223: return wfsCache;
224: }
225:
226: private WfDataAuditEvent dae = null;
227: private WfDataAuditEvent dae2 = null;
228: private WfStateAuditEvent sae = null;
229: private WfCreateProcessAuditEvent cpae = null;
230: private WfAssignmentAuditEvent aae = null;
231:
232: /* ********************************************************************* */
233: /* Test suite resources */
234: /* ********************************************************************* */
235:
236: /**
237: *
238: */
239: private WfProcess process = null;
240:
241: /* ********************************************************************* */
242: /* Test suite */
243: /* ********************************************************************* */
244:
245: /**
246: * Constructor of this TestCase
247: * @param name the name of the test case
248: */
249: public AuditTests(String name) {
250: super (name);
251: }
252:
253: /**
254: * The definition of the test suite. There's one test case per event type.
255: * However, not all test cases are currently doing something.
256: * @return the test suite
257: */
258: public static Test suite() {
259: TestSuite suite = new TestSuite();
260: suite.addTest(new AuditTests("importProcessDefinitions"));
261: suite.addTest(new AuditTests(
262: "createProcessAndProcessContextChanged"));
263: suite.addTest(new AuditTests("changeActivityResult"));
264: suite.addTest(new AuditTests("waitForCompletion"));
265: suite.addTest(new AuditTests("testFilters"));
266: suite.addTest(new AuditTests("testStateFilter"));
267: suite.addTest(new AuditTests("testClosedFilter"));
268: return new EJBClientTest(plc, suite);
269: }
270:
271: /* ********************************************************************* */
272: /* Test cases */
273: /* ********************************************************************* */
274:
275: /**
276: * Test case 1: Creates a process - calling AbstractProcess.init()
277: * @throws Exception ...
278: */
279: public void createProcessAndProcessContextChanged()
280: throws Exception {
281:
282: // create the required process
283: WfRequester req = new DefaultRequester(workflowService());
284: process = createProcess("ut-procdef-audit", "auditTest", req);
285: assertTrue(process != null);
286:
287: // wait some time because of asynchronous processing
288: long anfang = System.currentTimeMillis();
289: Thread.sleep(5000);
290: long diff = (System.currentTimeMillis() - anfang) / 1000;
291:
292: //displayAuditEvents(events);
293: checkAuditEventsForCreateProcess(process);
294: }
295:
296: /**
297: * Checks the collection of audit events for test case "createProcess"
298: * @param auditEvents the audit events to display
299: */
300: private void checkAuditEventsForCreateProcess(WfProcess process)
301: throws Exception {
302: // check audit event(s)
303: Collection auditEvents = process.history();
304:
305: assertTrue(process + ": expected 2 events, found "
306: + auditEvents.size(), auditEvents.size() == 2);
307: Iterator i = auditEvents.iterator();
308:
309: // the first event is required to signal the process creation
310: Object o = i.next();
311: Object o2;
312: if (!(o instanceof WfCreateProcessAuditEvent)) {
313: o2 = o;
314: o = i.next();
315: } else {
316: o2 = i.next();
317: }
318: assertTrue("Expected WfCreateProcessAuditEvent, found " + o,
319: o instanceof WfCreateProcessAuditEvent);
320: cpae = (WfCreateProcessAuditEvent) o;
321:
322: assertTrue(cpae.eventType().equals("processCreated"));
323: assertTrue(cpae.processName().equals("Audit Tests"));
324: assertTrue(cpae.activityKey() == null);
325: assertTrue(cpae.activityName() == null);
326: assertTrue(cpae.processMgrName().equals(
327: "ut-procdef-audit/auditTest"));
328: assertTrue(cpae.processMgrVersion().equals("1.42"));
329: assertTrue(cpae.pActivityKey() == null);
330: assertTrue(cpae.pProcessKey() == null);
331: assertTrue(cpae.pProcessName() == null);
332: assertTrue(cpae.pProcessMgrName() == null);
333: assertTrue(cpae.pProcessMgrVersion() == null);
334:
335: // the second event is required to signal a process context change
336: o = o2;
337: assertTrue(o instanceof WfDataAuditEvent);
338: dae = (WfDataAuditEvent) o;
339:
340: assertTrue(dae.eventType().equals("processContextChanged"));
341: assertTrue(dae.processName().equals("Audit Tests"));
342: assertTrue(dae.activityKey() == null);
343: assertTrue(dae.activityName() == null);
344: assertTrue(dae.processMgrName().equals(
345: "ut-procdef-audit/auditTest"));
346: assertTrue(dae.processMgrVersion().equals("1.42"));
347:
348: assertTrue(dae.oldData().isEmpty());
349: ProcessData newData = dae.newData();
350: assertTrue("Size should be 3, is " + newData.size(), newData
351: .size() == 3);
352: assertTrue(newData.keySet().contains("status"));
353: String data = (String) (newData.get("status"));
354: assertTrue(data == null);
355: assertTrue(newData.keySet().contains("testData"));
356: data = (String) (newData.get("testData"));
357: assertTrue(data.equals("relevante Process Test Daten"));
358: assertTrue(newData.keySet().contains("emailAddress"));
359: data = (String) (newData.get("emailAddress"));
360: assertTrue(data.equals("account@bank.com"));
361: }
362:
363: /* ********************************************************************* */
364:
365: /**
366: * Changes the activity result
367: * @throws Exception ...
368: */
369: public void changeActivityResult() throws Exception {
370:
371: // create the process
372: createProcessAndProcessContextChanged();
373:
374: // start the process
375: // since the first activity declared as "Automatic" it is started
376: // automatically calling the defined application setting a string
377: // which may be currently found in the log
378: process.start();
379:
380: // wait some time because of asynchronous processing
381: Thread.sleep(5000);
382:
383: // get first activity started automatically
384: WfActivity a = actByName(process, "A21");
385: // check audit event(s) of first activity
386: Collection activityEvents = a.history();
387: //displayAuditEvents(activityEvents);
388: checkAuditEventsForActivity21(activityEvents);
389:
390: // get second activity not started automatically
391: a = actByName(process, "A22");
392: // check audit event(s) of second activity
393: activityEvents = a.history();
394: //displayAuditEvents(activityEvents);
395: checkAuditEventsForActivityA22(activityEvents);
396:
397: // check audit event(s) of process
398: Collection processEvents = process.history();
399: //displayAuditEvents(processEvents);
400: checkProcessAuditEventsForChangeActivityResult(processEvents);
401: }
402:
403: /**
404: * Checks the collection of audit events for activty A21.
405: * @param auditEvents the audit events to display
406: */
407: private void checkAuditEventsForActivity21(Collection auditEvents) {
408:
409: assertTrue(auditEvents.size() == 3);
410: List sorted = new ArrayList(auditEvents);
411: Collections.sort(sorted, new Comparator() {
412: public int compare(Object o1, Object o2) {
413: if (((WfAuditEvent) o1).timeStamp().equals(
414: ((WfAuditEvent) o2).timeStamp())) {
415: return 0;
416: }
417: if (((WfAuditEvent) o1).timeStamp().before(
418: ((WfAuditEvent) o2).timeStamp())) {
419: return -1;
420: }
421: return 1;
422: }
423: });
424:
425: Iterator i = sorted.iterator();
426: // the first event is required to signal a state change
427: i.hasNext();
428: Object o = i.next();
429: assertTrue(o instanceof WfStateAuditEvent);
430: sae = (WfStateAuditEvent) o;
431:
432: assertTrue(sae.eventType().equals("activityStateChanged"));
433: assertTrue(sae.processName().equals("Audit Tests"));
434: assertTrue(sae.activityKey() != null);
435: assertTrue(sae.activityName().equals("A21"));
436: assertTrue(sae.processMgrName().equals(
437: "ut-procdef-audit/auditTest"));
438: assertTrue(sae.processMgrVersion().equals("1.42"));
439:
440: assertTrue(sae.oldState().startsWith(
441: "open.not_running.not_started"));
442: assertTrue(sae.newState().startsWith("open.running.running"));
443:
444: // the second event is required to signal an activity result change,
445: // timestamps aren't precise enough, though
446: Object dataEvent = i.next();
447: Object stateEvent = i.next();
448: if (stateEvent instanceof WfDataAuditEvent) {
449: assertTrue(((WfAuditEvent) stateEvent).timeStamp().equals(
450: ((WfAuditEvent) dataEvent).timeStamp()));
451: Object h = dataEvent;
452: dataEvent = stateEvent;
453: stateEvent = h;
454: }
455: o = dataEvent;
456: assertTrue(o instanceof WfDataAuditEvent);
457: dae = (WfDataAuditEvent) o;
458:
459: assertTrue(dae.eventType().equals("activityResultChanged"));
460: assertTrue(dae.processName().equals("Audit Tests"));
461: assertTrue(dae.activityKey() != null);
462: assertTrue(dae.activityName().equals("A21"));
463: assertTrue(dae.processMgrName().equals(
464: "ut-procdef-audit/auditTest"));
465: assertTrue(dae.processMgrVersion().equals("1.42"));
466:
467: assertTrue(dae.oldData().isEmpty());
468: ProcessData newData = dae.newData();
469: assertTrue(newData.size() == 1);
470: Iterator j = newData.keySet().iterator();
471: j.hasNext();
472: String key = (String) j.next();
473: assertTrue(key.equals("statusOut"));
474: String data = (String) (newData.get(key));
475: assertTrue(data.equals("Sent to: account@bank.com"));
476:
477: // the third event is required to signal a state change
478: o = stateEvent;
479: assertTrue(o instanceof WfStateAuditEvent);
480: sae = (WfStateAuditEvent) o;
481:
482: assertTrue(sae.eventType().equals("activityStateChanged"));
483: assertTrue(sae.processName().equals("Audit Tests"));
484: assertTrue(sae.activityKey() != null);
485: assertTrue(sae.activityName().equals("A21"));
486: assertTrue(sae.processMgrName().equals(
487: "ut-procdef-audit/auditTest"));
488: assertTrue(sae.processMgrVersion().equals("1.42"));
489:
490: assertTrue(sae.oldState().equals("open.running.running"));
491: assertTrue(sae.newState().startsWith("closed.completed"));
492: }
493:
494: /**
495: * Checks the collection of audit events for activty A21.
496: * @param auditEvents the audit events to display
497: */
498: private void checkAuditEventsForActivityA22(Collection auditEvents) {
499:
500: assertTrue(auditEvents.size() == 2);
501: List sorted = new ArrayList(auditEvents);
502: Collections.sort(sorted, new Comparator() {
503: public int compare(Object o1, Object o2) {
504: if (((WfAuditEvent) o1).timeStamp().equals(
505: ((WfAuditEvent) o2).timeStamp())) {
506: return 0;
507: }
508: if (((WfAuditEvent) o1).timeStamp().before(
509: ((WfAuditEvent) o2).timeStamp())) {
510: return -1;
511: }
512: return 1;
513: }
514: });
515: Iterator i = sorted.iterator();
516:
517: // the first event is required to signal a state change
518: i.hasNext();
519: Object o = i.next();
520: assertTrue(o instanceof WfStateAuditEvent);
521: sae = (WfStateAuditEvent) o;
522:
523: assertTrue(sae.eventType().equals("activityStateChanged"));
524: assertTrue(sae.processName().equals("Audit Tests"));
525: assertTrue(sae.activityKey() != null);
526: assertTrue(sae.activityName().equals("A22"));
527: assertTrue(sae.processMgrName().equals(
528: "ut-procdef-audit/auditTest"));
529: assertTrue(sae.processMgrVersion().equals("1.42"));
530:
531: assertTrue(sae.oldState().startsWith(
532: "open.not_running.not_started"));
533: assertTrue(sae.newState().startsWith("open.running.running"));
534: //assertTrue(sae.newState().equals("open.running.started"));
535:
536: // the second event is required to signal a state change
537: i.hasNext();
538: o = i.next();
539: assertTrue(o instanceof WfStateAuditEvent);
540: sae = (WfStateAuditEvent) o;
541:
542: assertTrue(sae.eventType().equals("activityStateChanged"));
543: assertTrue(sae.processName().equals("Audit Tests"));
544: assertTrue(sae.activityKey() != null);
545: assertTrue(sae.activityName().equals("A22"));
546: assertTrue(sae.processMgrName().equals(
547: "ut-procdef-audit/auditTest"));
548: assertTrue(sae.processMgrVersion().equals("1.42"));
549:
550: assertTrue(sae.oldState().startsWith("open.running.running"));
551: assertTrue(sae.newState().startsWith(
552: "open.not_running.suspended"));
553: }
554:
555: /**
556: * Checks the collection of audit events for test case "createProcess"
557: * @param auditEvents the audit events to display
558: */
559: private void checkProcessAuditEventsForChangeActivityResult(
560: Collection auditEvents) {
561:
562: assertTrue(auditEvents.size() == 4);
563: SortedMap sorted = new TreeMap();
564: for (Iterator i = auditEvents.iterator(); i.hasNext();) {
565: WfAuditEvent ae = (WfAuditEvent) i.next();
566: sorted.put(ae.timeStamp(), ae);
567: }
568:
569: for (Iterator i = sorted.values().iterator(); i.hasNext();) {
570: Object o = i.next();
571: if (o instanceof WfCreateProcessAuditEvent) {
572: cpae = (WfCreateProcessAuditEvent) o;
573: } else if ((o instanceof WfDataAuditEvent) && dae == null) {
574: dae = (WfDataAuditEvent) o;
575: } else if (o instanceof WfStateAuditEvent) {
576: sae = (WfStateAuditEvent) o;
577: } else if (o instanceof WfDataAuditEvent) {
578: dae2 = (WfDataAuditEvent) o;
579: }
580: }
581: assertTrue(cpae != null);
582: assertTrue(dae != null);
583: assertTrue(sae != null);
584: assertTrue(dae2 != null);
585:
586: assertTrue(sae.eventType().equals("processStateChanged"));
587: assertTrue(sae.processName().equals("Audit Tests"));
588: assertTrue(sae.activityKey() == null);
589: assertTrue(sae.activityName() == null);
590: assertTrue(sae.processMgrName().equals(
591: "ut-procdef-audit/auditTest"));
592: assertTrue(sae.processMgrVersion().equals("1.42"));
593:
594: assertTrue(sae.oldState()
595: .equals("open.not_running.not_started"));
596: assertTrue(sae.newState().equals("open.running.running"));
597:
598: assertTrue(dae2.eventType().equals("processContextChanged"));
599: assertTrue(dae2.processName().equals("Audit Tests"));
600: assertTrue(dae2.activityKey() == null);
601: assertTrue(dae2.activityName() == null);
602: assertTrue(dae2.processMgrName().equals(
603: "ut-procdef-audit/auditTest"));
604: assertTrue(dae2.processMgrVersion().equals("1.42"));
605:
606: ProcessData oldData = dae2.oldData();
607: assertTrue(oldData.size() == 1);
608: Iterator j = oldData.keySet().iterator();
609: j.hasNext();
610: String key = (String) j.next();
611: assertTrue(key.equals("status"));
612: String data = (String) (oldData.get(key));
613: assertTrue(data == null);
614:
615: ProcessData newData = dae2.newData();
616: assertTrue(newData.size() == 1);
617: Iterator k = newData.keySet().iterator();
618: k.hasNext();
619: key = (String) k.next();
620: assertTrue(key.equals("status"));
621: data = (String) (newData.get(key));
622: assertTrue(data.equals("Sent to: account@bank.com"));
623: }
624:
625: public void waitForCompletion() throws Exception {
626: // Obtain subscriber
627: EventSubscriber subs = workflowService()
628: .createEventSubscriber();
629:
630: // create the required process
631: WfRequester req = new DefaultRequester(workflowService());
632: process = createProcess("ut-procdef-audit", "auditTest2", req);
633: String procKey = process.key();
634: assertTrue(process != null);
635: process.start();
636:
637: WfAuditEvent e = null;
638: while (true) {
639: e = subs.receive(5000);
640: assertTrue("Timeout receiving event", e != null);
641: if (e.eventType()
642: .equals(WfAuditEvent.PROCESS_STATE_CHANGED)
643: && e.processKey().equals(procKey)
644: && ((WfStateAuditEvent) e).newState().startsWith(
645: "closed")) {
646: break;
647: }
648: }
649: assertTrue(e instanceof ProcessClosedAuditEvent);
650: ProcessData res = ((ProcessClosedAuditEvent) e).result();
651: assertTrue(res.keySet().size() == 2);
652: assertTrue(res.keySet().contains("outVal1"));
653: assertTrue(res.keySet().contains("inOutVal1"));
654: assertTrue(subs.receive(2500) == null);
655: workflowService().release(subs);
656: }
657:
658: public void testFilters() throws Exception {
659: // Obtain subscribers
660: EventSubscriber subs = workflowService()
661: .createEventSubscriber();
662:
663: // create the required process
664: WfRequester req = new DefaultRequester(workflowService());
665: process = createProcess("ut-procdef-audit", "auditTest2", req);
666: String procKey = process.key();
667: assertTrue(process != null);
668:
669: // additional subscribers
670: final int[] counters = new int[5];
671: EventSubscriber subsAll = workflowService()
672: .createEventSubscriber();
673: subsAll.setEventHandler(new WfAuditHandler() {
674: public void receiveEvent(WfAuditEvent e) {
675: counters[0] += 1;
676: }
677: });
678: EventSubscriber subsProc = workflowService()
679: .createEventSubscriber(procKey, null);
680: subsProc.setEventHandler(new WfAuditHandler() {
681: public void receiveEvent(WfAuditEvent e) {
682: counters[1] += 1;
683: }
684: });
685: EventSubscriber subsPSC = workflowService()
686: .createEventSubscriber(procKey,
687: WfAuditEvent.PROCESS_STATE_CHANGED);
688: subsPSC.setEventHandler(new WfAuditHandler() {
689: public void receiveEvent(WfAuditEvent e) {
690: assertTrue(e.eventType().equals(
691: WfAuditEvent.PROCESS_STATE_CHANGED));
692: counters[2] += 1;
693: }
694: });
695: EventSubscriber subsASC = workflowService()
696: .createEventSubscriber(procKey,
697: WfAuditEvent.ACTIVITY_STATE_CHANGED);
698: subsASC.setEventHandler(new WfAuditHandler() {
699: public void receiveEvent(WfAuditEvent e) {
700: assertTrue(e.eventType().equals(
701: WfAuditEvent.ACTIVITY_STATE_CHANGED));
702: counters[3] += 1;
703: }
704: });
705: EventSubscriber subsPASC = workflowService()
706: .createEventSubscriber(
707: procKey,
708: WfAuditEvent.PROCESS_STATE_CHANGED + ", "
709: + WfAuditEvent.ACTIVITY_STATE_CHANGED);
710: subsPASC.setEventHandler(new WfAuditHandler() {
711: public void receiveEvent(WfAuditEvent e) {
712: assertTrue(e.eventType().equals(
713: WfAuditEvent.PROCESS_STATE_CHANGED)
714: || e.eventType().equals(
715: WfAuditEvent.ACTIVITY_STATE_CHANGED));
716: counters[4] += 1;
717: }
718: });
719:
720: process.start();
721:
722: while (true) {
723: WfAuditEvent e = subs.receive(5000);
724: assertTrue("Timeout receiving event", e != null);
725: if (e.eventType()
726: .equals(WfAuditEvent.PROCESS_STATE_CHANGED)
727: && e.processKey().equals(procKey)
728: && ((WfStateAuditEvent) e).newState().startsWith(
729: "closed")) {
730: break;
731: }
732: }
733:
734: // allow delivery of events
735: Thread.sleep(2500);
736:
737: assertTrue("All events: " + counters[0] + " (should be >= 14)",
738: counters[0] >= 14);
739: assertTrue("Process events: " + counters[1]
740: + " (should be 14 or 15)", 14 <= counters[1]
741: && counters[1] <= 16);
742: assertTrue("Process state changes: " + counters[2]
743: + " (should be 2)", counters[2] == 2);
744: assertTrue("Activity state changes: " + counters[3]
745: + " (should be 8)", counters[3] == 8);
746: assertTrue("All state changes: " + counters[4]
747: + " (should be 10)", counters[4] == 10);
748:
749: workflowService().release(subs);
750: workflowService().release(subsAll);
751: workflowService().release(subsProc);
752: workflowService().release(subsPSC);
753: workflowService().release(subsASC);
754: workflowService().release(subsPASC);
755: }
756:
757: public void testStateFilter() throws Exception {
758: // Obtain subscribers
759: // create the required process
760: WfRequester req = new DefaultRequester(workflowService());
761: process = createProcess("ut-procdef-audit", "auditStateOnly",
762: req);
763: assertTrue(process != null);
764: process.start();
765: assertTrue(stateReached(process, "closed"));
766: int hs = process.history().size();
767: for (Iterator i = process.steps().iterator(); i.hasNext();) {
768: WfActivity act = (WfActivity) i.next();
769: hs += act.history().size();
770: }
771: assertTrue("History size should be 4, is " + hs, hs == 4);
772: }
773:
774: public void testClosedFilter() throws Exception {
775: // Obtain subscribers
776: // create the required process
777: WfRequester req = new DefaultRequester(workflowService());
778: process = createProcess("ut-procdef-audit",
779: "auditProcClosedOnly", req);
780: assertTrue(process != null);
781: process.start();
782: assertTrue(stateReached(process, "closed"));
783: int hs = process.history().size();
784: for (Iterator i = process.steps().iterator(); i.hasNext();) {
785: WfActivity act = (WfActivity) i.next();
786: hs += act.history().size();
787: }
788: assertTrue(hs == 1);
789: }
790:
791: /* ********************************************************************* */
792: /* HELPER methods */
793: /* ********************************************************************* */
794:
795: private WfActivity actByName(WfProcess proc, String name)
796: throws Exception {
797: WfActivity a = null;
798: for (Iterator it = proc.steps().iterator(); it.hasNext();) {
799: WfActivity ai = (WfActivity) it.next();
800: if (ai.name().equals(name)) {
801: a = ai;
802: break;
803: }
804: }
805: return a;
806: }
807:
808: /**
809: * Import the process definitions from a XPDL file
810: * unsing the ProcessDefinitionDirectory.
811: */
812: public void importProcessDefinitions() throws Exception {
813: ProcessDefinitionDirectory pdd = null;
814: try {
815: pdd = workflowService().processDefinitionDirectory();
816:
817: InputStream is = getClass().getResourceAsStream(
818: "/process/auditing.xml");
819: assertTrue(is != null);
820: BufferedReader br = new BufferedReader(
821: new InputStreamReader(is, "ISO-8859-1"));
822: StringBuffer sb = new StringBuffer();
823: String st;
824: while ((st = br.readLine()) != null) {
825: sb.append(st + "\n");
826: }
827: pdd.importProcessDefinitions(sb.toString());
828: Collection processDefinitions = pdd.processDefinitions();
829: assertTrue(processDefinitions.size() > 1);
830: } finally {
831: workflowService().release(pdd);
832: }
833: }
834:
835: /**
836: * Creates the process
837: * using the ProcessDefinitionDirectory bean.
838: */
839: private WfProcess createProcess(String pkgId, String prcId,
840: WfRequester req) throws Exception {
841: ProcessDefinitionDirectory procDir = null;
842: try {
843: procDir = workflowService().processDefinitionDirectory();
844: ProcessMgr pmgr = procDir.processMgr(pkgId, prcId);
845: return pmgr.createProcess(req);
846: } finally {
847: workflowService().release(procDir);
848: }
849: }
850:
851: private boolean stateReached(WfProcess proc, String procState)
852: throws Exception {
853: int maxRetries = 30;
854: while (true) {
855: if (proc.state().startsWith(procState)) {
856: return true;
857: }
858: if (maxRetries-- <= 0) {
859: return false;
860: }
861: Thread.sleep(1000);
862: }
863: }
864:
865: /**
866: * Displays the collection of process data
867: * @param processData the process data to display
868: */
869: private void displayProcessData(ProcessData processData) {
870: for (Iterator i = processData.keySet().iterator(); i.hasNext();) {
871: String key = (String) i.next();
872: Object o = processData.get(key);
873: System.err.println(key + " = " + o);
874: }
875: }
876:
877: /**
878: * Displays the collection of audit events
879: * @param auditEvents the audit events to display
880: */
881: private void displayAuditEvents(Collection auditEvents) {
882: for (Iterator i = auditEvents.iterator(); i.hasNext();) {
883: Object o = i.next();
884: WfAuditEvent ae = (WfAuditEvent) o;
885: System.err.println(" --------------------- ");
886: System.err.println(" event type = " + ae.eventType());
887: System.err.println(" time stamp = " + ae.timeStamp());
888: System.err.println(" activity key = " + ae.activityKey());
889: System.err.println(" activity name = " + ae.activityName());
890: System.err.println(" process key = " + ae.processKey());
891: System.err.println(" process name = " + ae.processName());
892: System.err.println(" process manager name = "
893: + ae.processMgrName());
894: System.err.println(" process manager version = "
895: + ae.processMgrVersion());
896: if (o instanceof WfAssignmentAuditEvent) {
897: WfAssignmentAuditEvent aae = (WfAssignmentAuditEvent) o;
898: System.err.println(" old resource key = "
899: + aae.oldResourceKey());
900: System.err.println(" new resource key = "
901: + aae.newResourceKey());
902: System.err.println(" old resource name = "
903: + aae.oldResourceName());
904: System.err.println(" new resource name = "
905: + aae.newResourceName());
906: } else if (o instanceof WfCreateProcessAuditEvent) {
907: WfCreateProcessAuditEvent cpae = (WfCreateProcessAuditEvent) o;
908: System.err.println(" parent activity key = "
909: + cpae.pActivityKey());
910: System.err.println(" parent process key = "
911: + cpae.pProcessKey());
912: System.err.println(" parent process name = "
913: + cpae.pProcessName());
914: System.err.println(" parent process manager name = "
915: + cpae.pProcessMgrName());
916: System.err.println(" parent process manager version = "
917: + cpae.pProcessMgrVersion());
918: } else if (o instanceof WfDataAuditEvent) {
919: WfDataAuditEvent dae = (WfDataAuditEvent) o;
920: System.err.println(" old data = " + dae.oldData());
921: System.err.println(" new data = " + dae.newData());
922: } else if (o instanceof WfStateAuditEvent) {
923: WfStateAuditEvent sae = (WfStateAuditEvent) o;
924: System.err.println(" old state = " + sae.oldState());
925: System.err.println(" new state = " + sae.newState());
926: }
927: }
928: }
929: }
|