001: package org.concern.controller;
002:
003: import junit.framework.TestCase;
004: import org.hibernate.cfg.Configuration;
005: import org.concern.*;
006: import org.concern.Log;
007: import org.hibernate.*;
008:
009: import java.util.*;
010:
011: /** @noinspection ALL*/
012: // NOTE: @noinspection ALL is to prevent IntelliJ IDEA from displaying
013: // (many!) warnings if you happen to be in a project with 1.5 syntax
014: // enabled.
015: public class ControllerTest extends TestCase {
016: Controller controller;
017: SessionFactory sessionFactory;
018: private boolean throwException;
019:
020: public ControllerTest(String name) {
021: super (name);
022: }
023:
024: protected void setUp() throws Exception {
025: initializeController();
026:
027: Session session = sessionFactory.openSession();
028: Transaction transaction = session.beginTransaction();
029: ScrollableResults results = session.createQuery("FROM Subject")
030: .scroll();
031: while (results.next()) {
032: Subject subject = (Subject) results.get()[0];
033: session.delete(subject);
034: }
035: results = session.createQuery("FROM ArchiveLog").scroll();
036: while (results.next()) {
037: ArchiveLog archive = (ArchiveLog) results.get()[0];
038: session.delete(archive);
039: }
040: transaction.commit();
041: session.close();
042: }
043:
044: protected void initializeController() {
045: Configuration configuration = new Configuration();
046: configuration.configure("controller-hibernate.cfg.xml");
047: configuration.addResource("Controller.hbm.xml");
048:
049: sessionFactory = configuration.buildSessionFactory();
050: controller = new Controller("ControllerTest");
051: controller.setLoader(new DummyLoader());
052: controller.setSessionFactory(sessionFactory);
053: }
054:
055: protected void tearDown() throws Exception {
056: for (Iterator iterator = controller.getSubjects(
057: Controller.STATE_RUNNING).iterator(); iterator
058: .hasNext();) {
059: String userValue = (String) iterator.next();
060: controller.destroySubject(userValue);
061: }
062: controller.timeout();
063: }
064:
065: public void testCreateAndRemoveSubject() throws Exception {
066: String userValue = "createAndRemoveSubject"
067: + Thread.currentThread().getName();
068: controller.createSubject(userValue);
069: Subject subject = getSubject(userValue);
070: assertNotNull(subject);
071: assertEquals(userValue, subject.getUserValue());
072: controller.destroySubject(userValue);
073: controller.timeout();
074: subject = getSubject(userValue);
075: assertNull(subject);
076: }
077:
078: private Subject getSubject(String userValue) throws Exception {
079: controller.transactionManager.begin();
080: List list = controller.sessions.getSession().createQuery(
081: "FROM " + Subject.class.getName()
082: + " AS s WHERE s.userValue = '" + userValue
083: + "'").list();
084: Subject subject = list.size() == 1 ? (Subject) list.get(0)
085: : null;
086: if (subject != null) {
087: subject.getLogs().size();
088: subject.getEnlistments().size();
089: }
090: controller.transactionManager.commit();
091: return subject;
092: }
093:
094: public void testGetSubjects() throws Exception {
095: controller.createSubject("getSubjects_1"
096: + Thread.currentThread().getName());
097: controller.createSubject("getSubjects_2"
098: + Thread.currentThread().getName());
099: List subjects = controller
100: .getSubjects(Controller.STATE_RUNNING);
101: int size = subjects.size();
102: subjects.removeAll(Arrays.asList(new String[] {
103: "getSubjects_1" + Thread.currentThread().getName(),
104: "getSubjects_2" + Thread.currentThread().getName() }));
105: assertEquals(2, size - subjects.size());
106: controller.destroySubject("getSubjects_1"
107: + Thread.currentThread().getName());
108: controller.destroySubject("getSubjects_2"
109: + Thread.currentThread().getName());
110: controller.timeout();
111: }
112:
113: public void testScheduleAnnouncement() throws Exception {
114: String userValue = "scheduleAnnouncement"
115: + Thread.currentThread().getName();
116: controller.createSubject(userValue);
117: controller.scheduleAnnouncement(userValue, 10);
118: Subject subject = getSubject(userValue);
119: Enlistment enlistment = (Enlistment) subject.getEnlistments()
120: .first();
121: assertTrue(enlistment.getTimeout() <= System
122: .currentTimeMillis() + 10000);
123: controller.destroySubject(userValue);
124: controller.timeout();
125: }
126:
127: public void testEnlistments() throws Exception {
128: String userValue = "testEnlistment"
129: + Thread.currentThread().getName();
130: List activities = new LinkedList();
131: activities.add(new DummyAsynchronousActivity("async_a"));
132: activities.add(new DummyAsynchronousActivity("async_b"));
133: activities.add(new DummySynchronousActivity("sync_c"));
134: controller.setActivities(activities);
135: List conditions = new LinkedList();
136: conditions.add(new DummyCondition("async_a"));
137: conditions.add(new DummyCondition("async_b"));
138: conditions.add(new DummyCondition("sync_c"));
139: controller.setConditions(conditions);
140:
141: controller.createSubject(userValue);
142: controller.process(userValue);
143:
144: List enlistments = controller.getEnlistments(userValue);
145: assertEquals("" + enlistments, 2, enlistments.size());
146:
147: enlistments = controller.getSubjects("async_a");
148: assertEquals("" + enlistments, 1, enlistments.size());
149: assertEquals(userValue, enlistments.get(0));
150: controller.complete(userValue, "async_a");
151: enlistments = controller.getSubjects("async_a");
152: assertEquals(0, enlistments.size());
153:
154: enlistments = controller.getSubjects("async_b");
155: assertEquals(1, enlistments.size());
156: assertEquals(userValue, enlistments.get(0));
157: controller.complete(userValue, "async_b");
158: enlistments = controller.getSubjects("async_b");
159: assertEquals(0, enlistments.size());
160:
161: enlistments = controller.getSubjects("sync_c");
162: assertEquals(0, enlistments.size());
163: controller.destroySubject(userValue);
164: controller.timeout();
165: }
166:
167: public void testLogAndArchive() throws Exception {
168: String userValue = "testLogAndArchive"
169: + Thread.currentThread().getName();
170: List activities = new LinkedList();
171: activities.add(new DummyAsynchronousActivity("async_a"));
172: activities.add(new DummyAsynchronousActivity("async_b"));
173: activities.add(new DummySynchronousActivity("sync_c"));
174: controller.setActivities(activities);
175: List conditions = new LinkedList();
176: conditions.add(new DummyCondition("async_a"));
177: conditions.add(new DummyCondition("async_b"));
178: conditions.add(new DummyCondition("sync_c"));
179: controller.setConditions(conditions);
180:
181: controller.createSubject(userValue);
182: controller.process(userValue);
183: controller.complete(userValue, "async_a");
184: controller.complete(userValue, "async_b");
185: List logs = controller.getLog(userValue);
186: controller.destroySubject(userValue);
187: controller.timeout();
188: List archives = controller.getArchive(userValue);
189:
190: assertEquals("" + logs, 4, logs.size());
191: assertEquals("" + archives, 5, archives.size());
192: for (int i = 0; i < 3; i++) {
193: Log log = (Log) logs.get(i);
194: Log archive = (Log) archives.get(i);
195: assertEquals(log.getUserValue(), archive.getUserValue());
196: assertEquals(log.getMessage(), archive.getMessage());
197: assertEquals(log.getActivity(), archive.getActivity());
198: assertEquals(log.getTimestamp().getTime(), archive
199: .getTimestamp().getTime());
200: assertEquals(log.isSuccess(), archive.isSuccess());
201: }
202: System.out.println("archives = " + archives);
203: Log archive = (Log) archives.get(archives.size() - 1);
204: assertEquals(userValue, archive.getUserValue());
205: assertEquals("DESTROYED", archive.getActivity());
206: assertEquals(true, archive.isSuccess());
207: }
208:
209: public void testExecuteSynchronous() throws Exception {
210: String userValue = "testExecuteSynchronous"
211: + Thread.currentThread().getName();
212: List activities = new LinkedList();
213: activities.add(new DummySynchronousActivity("sync_success"));
214: activities.add(new DummySynchronousActivity("sync_exception") {
215: public void execute(Object subject)
216: throws ActivityExecutionException {
217: throw new ActivityExecutionException("sync_exception");
218: }
219:
220: public void escalate(Object subject)
221: throws ActivityExecutionException {
222: environment.put("activity.precondition", "!x");
223: }
224:
225: public int getTrials() {
226: return 2;
227: }
228:
229: public int getRetryDelay() {
230: return 0;
231: }
232: });
233: activities.add(new DummySynchronousActivity(
234: "sync_postcondition") {
235: public void setController(Controller controller) {
236: super .setController(controller);
237: environment.put("activity.postcondition", "!x");
238: }
239:
240: public void escalate(Object subject)
241: throws ActivityExecutionException {
242: environment.put("activity.precondition", "!x");
243: }
244:
245: public int getTrials() {
246: return 2;
247: }
248:
249: public int getRetryDelay() {
250: return 3600;
251: }
252: });
253: controller.setActivities(activities);
254: List conditions = new LinkedList();
255: conditions.add(new DummyCondition("sync_success"));
256: conditions.add(new DummyCondition("sync_exception"));
257: conditions.add(new DummyCondition("sync_postcondition"));
258: conditions.add(new DummyCondition("x"));
259: controller.setConditions(conditions);
260:
261: controller.createSubject(userValue);
262: controller.process(userValue);
263: List logs = controller.getLog(userValue);
264: System.out.println("logs = " + logs);
265: for (Iterator iterator = logs.iterator(); iterator.hasNext();) {
266: Log log = (Log) iterator.next();
267: if ("sync_success".equals((log.getActivity()))) {
268: assertEquals(true, log.isSuccess());
269: assertEquals("EXECUTED", log.getMessage());
270: } else if ("sync_exception".equals((log.getActivity()))) {
271: assertEquals(false, log.isSuccess());
272: if ("FAILED".equals(log.getMessage()))
273: assertEquals("sync_exception", log.getDetails());
274: else
275: assertEquals("ESCALATED", log.getMessage());
276: } else if ("sync_postcondition".equals((log.getActivity()))) {
277: assertEquals(false, log.isSuccess());
278: if ("FAILED".equals(log.getMessage()))
279: assertTrue(log.getDetails().startsWith(
280: "postcondition - "));
281: else
282: assertEquals("ESCALATED", log.getMessage());
283: } else if (!"CREATED".equals(log.getActivity())
284: && !"STALLED".equals(log.getActivity()))
285: fail(log.getActivity());
286: }
287:
288: Subject subject = getSubject(userValue);
289: SortedSet enlistments = subject.getEnlistments();
290: for (Iterator iterator = enlistments.iterator(); iterator
291: .hasNext();) {
292: Enlistment enlistment = (Enlistment) iterator.next();
293: if ("RETRY".equals(enlistment.getCommand())
294: && "sync_postcondition".equals(enlistment
295: .getActivity())) {
296: assertTrue(System.currentTimeMillis() + 3600000 > enlistment
297: .getTimeout());
298: assertTrue(System.currentTimeMillis() + 3500000 < enlistment
299: .getTimeout());
300: }
301: }
302: System.out.println("subject.getLogs() = " + subject.getLogs());
303: controller.destroySubject(userValue);
304: controller.timeout();
305: }
306:
307: public void testExecuteAsynchronous() throws Exception {
308: String userValue = "testExecuteAsynchronous"
309: + Thread.currentThread().getName();
310: List activities = new LinkedList();
311: activities.add(new DummyAsynchronousActivity("async_success"));
312: activities.add(new DummyAsynchronousActivity("async_timeout") {
313: {
314: getEnvironment()
315: .put("activity.timeout", new Integer(0));
316: }
317:
318: public void escalate(Object subject)
319: throws ActivityExecutionException {
320: environment.put("activity.precondition", "!x");
321: }
322: });
323: activities.add(new DummyAsynchronousActivity(
324: "async_postcondition") {
325: public void setController(Controller controller) {
326: super .setController(controller);
327: environment.put("activity.postcondition", "!x");
328: }
329:
330: public void escalate(String subject)
331: throws ActivityExecutionException {
332: environment.put("activity.precondition", "!x");
333: }
334: });
335: controller.setActivities(activities);
336: List conditions = new LinkedList();
337: conditions.add(new DummyCondition("async_success"));
338: conditions.add(new DummyCondition("async_timeout"));
339: conditions.add(new DummyCondition("async_postcondition"));
340: conditions.add(new DummyCondition("x"));
341: controller.setConditions(conditions);
342:
343: controller.createSubject(userValue);
344: controller.process(userValue);
345: boolean success = controller.complete(userValue,
346: "async_success");
347: assertTrue(success);
348: success = controller.complete(userValue, "async_postcondition");
349: assertFalse(success);
350: controller.process(userValue);
351:
352: List logs = controller.getLog(userValue);
353: for (Iterator iterator = logs.iterator(); iterator.hasNext();) {
354: Log log = (Log) iterator.next();
355: if ("async_success".equals((log.getActivity()))) {
356: assertEquals(true, log.isSuccess());
357: assertEquals("EXECUTED", log.getMessage());
358: } else if ("async_timeout".equals((log.getActivity()))) {
359: assertEquals(false, log.isSuccess());
360: assertEquals("ESCALATED", log.getMessage());
361: } else if ("async_postcondition"
362: .equals((log.getActivity()))) {
363: assertEquals(false, log.isSuccess());
364: assertEquals("FAILED", log.getMessage());
365: assertEquals("NOT COMPLETE", log.getDetails());
366: } else if (!"CREATED".equals(log.getActivity()))
367: fail(log.getActivity());
368: }
369: controller.destroySubject(userValue);
370: controller.timeout();
371: }
372:
373: public void testExecuteEvent() throws Exception {
374: String userValue = "testExecuteEvent"
375: + Thread.currentThread().getName();
376: List events = new LinkedList();
377: events.add(new DummyEvent("event_occured"));
378: events.add(new DummyEvent("event_not_occured") {
379: public void setController(Controller controller) {
380: super .setController(controller);
381: environment.put("event.postcondition", "!x");
382: }
383: });
384: controller.setEvents(events);
385: List conditions = new LinkedList();
386: conditions.add(new DummyCondition("event_occured"));
387: conditions.add(new DummyCondition("event_not_occured"));
388: conditions.add(new DummyCondition("x"));
389: controller.setConditions(conditions);
390:
391: controller.createSubject(userValue);
392: boolean success = controller.notify(userValue, "event_occured");
393: assertTrue(success);
394: success = controller.notify(userValue, "event_not_occured");
395: assertFalse(success);
396:
397: List logs = controller.getLog(userValue);
398: boolean occured = false;
399: for (Iterator iterator = logs.iterator(); iterator.hasNext();) {
400: Log log = (Log) iterator.next();
401: if ("event_occured".equals((log.getActivity()))) {
402: assertEquals(true, log.isSuccess());
403: assertEquals("EXECUTED", log.getMessage());
404: occured = true;
405: } else if ("event_not_occured".equals((log.getActivity()))) {
406: assertEquals(false, log.isSuccess());
407: assertEquals("FAILED", log.getMessage());
408: occured = true;
409: } else if (!"CREATED".equals(log.getActivity()))
410: fail(log.getActivity());
411: }
412: assertTrue(occured);
413: controller.destroySubject(userValue);
414: controller.timeout();
415: }
416:
417: public void testExecuteListener() throws Exception {
418: String userValue = "testExecuteListener"
419: + Thread.currentThread().getName();
420: List listeners = new LinkedList();
421: listeners.add(new DummyListener("listener_success"));
422: listeners.add(new DummyListener("listener_exception") {
423: public void notify(Object tsubject)
424: throws ActivityExecutionException {
425: throw new ActivityExecutionException(
426: "listener_exception");
427: }
428:
429: public void escalate(Object subject)
430: throws ActivityExecutionException {
431: environment.put("listener.precondition", "!x");
432: }
433: });
434: controller.setListeners(listeners);
435: List conditions = new LinkedList();
436: conditions.add(new DummyCondition("listener_success"));
437: conditions.add(new DummyCondition("listener_exception"));
438: conditions.add(new DummyCondition("x"));
439: controller.setConditions(conditions);
440: controller.setEvents(Collections.EMPTY_LIST);
441: controller.setActivities(Collections.EMPTY_LIST);
442:
443: controller.createSubject(userValue);
444: controller.process(userValue);
445:
446: List logs = controller.getLog(userValue);
447: boolean notified = false;
448: boolean failed = false;
449: for (Iterator iterator = logs.iterator(); iterator.hasNext();) {
450: Log log = (Log) iterator.next();
451: if ("listener_success".equals((log.getActivity()))) {
452: assertEquals(true, log.isSuccess());
453: assertEquals("EXECUTED", log.getMessage());
454: notified = true;
455: } else if ("listener_exception".equals((log.getActivity()))) {
456: assertEquals(false, log.isSuccess());
457: if ("FAILED".equals(log.getMessage()))
458: assertEquals("listener_exception", log.getDetails());
459: else
460: assertEquals("ESCALATED", log.getMessage());
461: failed = true;
462: } else if (!"CREATED".equals(log.getActivity())
463: && !"STALLED".equals(log.getActivity()))
464: fail(log.getActivity());
465: }
466: assertTrue(notified);
467: assertTrue(failed);
468: controller.destroySubject(userValue);
469: controller.timeout();
470: }
471:
472: public void testTemporalConditions() throws Exception {
473: String userValue = "temporalConditions"
474: + Thread.currentThread().getName();
475: long millis = System.currentTimeMillis() + 1000;
476: List conditions = new LinkedList();
477: conditions.add(new DummyTemporalCondition("temporalCondition",
478: false, millis));
479: controller.setConditions(conditions);
480: controller.setLoader(new DummyLoader());
481: controller.setEvents(Collections.EMPTY_LIST);
482: controller.setActivities(Collections.EMPTY_LIST);
483: controller.setListeners(Collections.EMPTY_LIST);
484:
485: controller.createSubject(userValue);
486: controller.process(userValue);
487:
488: Subject subject = getSubject(userValue);
489: Enlistment enlistment = (Enlistment) subject.getEnlistments()
490: .first();
491: assertEquals(millis, enlistment.getTimeout());
492:
493: controller.destroySubject(userValue);
494: controller.timeout();
495: }
496:
497: public void testTimerTask() throws Exception {
498: controller.setTimerInterval(1000);
499: controller.start();
500:
501: String userValue = "testTimerTask"
502: + Thread.currentThread().getName();
503: controller.createSubject(userValue);
504: controller.announceSubject(userValue);
505:
506: Subject subject = getSubject(userValue);
507: assertEquals(1, subject.getEnlistments().size());
508: Thread.sleep(2000);
509: subject = getSubject(userValue);
510: assertEquals("" + subject.getEnlistments(), 0, subject
511: .getEnlistments().size());
512: controller.stop();
513: controller.destroySubject(userValue);
514: controller.timeout();
515: }
516:
517: public void testSubjectNotFound() throws Exception {
518: String userValue = "testSubjectNotFound"
519: + Thread.currentThread().getName();
520: throwException = false;
521: controller.setLoader(new DummyLoader() {
522: public Object load(String id)
523: throws SubjectNotFoundException {
524: if (throwException)
525: throw new SubjectNotFoundException(id);
526: return id;
527: }
528:
529: public String idOf(Object subject)
530: throws SubjectNotFoundException {
531: if (throwException)
532: throw new SubjectNotFoundException("" + subject);
533: return subject.toString();
534: }
535: });
536: List activities = new LinkedList();
537: activities.add(new DummyAsynchronousActivity("async"));
538: activities.add(new DummySynchronousActivity("sync"));
539: controller.setActivities(activities);
540: List events = new LinkedList();
541: events.add(new DummyEvent("event"));
542: controller.setEvents(events);
543: List listeners = new LinkedList();
544: listeners.add(new DummyListener("event"));
545: controller.setListeners(listeners);
546:
547: controller.createSubject(userValue);
548: throwException = true;
549: try {
550: controller.complete(userValue, "async");
551: fail("expected UnknownSubjectException");
552: } catch (ControllerException e) {
553: assertEquals(userValue, e.getMessage());
554: }
555:
556: try {
557: controller.notify(userValue, "event");
558: fail("expected UnknownSubjectException");
559: } catch (ControllerException e) {
560: assertEquals(userValue, e.getMessage());
561: }
562:
563: controller.process(userValue);
564: controller.destroySubject(userValue);
565: controller.process(userValue);
566: List archive = controller.getArchive(userValue);
567:
568: boolean load_failed = false;
569: boolean suspended = false;
570: boolean destroyed = false;
571: for (Iterator iterator = archive.iterator(); iterator.hasNext();) {
572: Log log = (Log) iterator.next();
573: if ("LOAD".equals((log.getActivity())))
574: load_failed = true;
575: else if ("SUSPENDED".equals((log.getActivity())))
576: suspended = true;
577: else if ("DESTROYED".equals((log.getActivity())))
578: destroyed = true;
579: }
580: assertTrue(load_failed);
581: assertTrue(suspended);
582: assertTrue(destroyed);
583: }
584:
585: /**
586: * Test bug: if the subject is dirtied (by mutating one of its collections)
587: * during a transaction, and then that transaction is rolled back (as is the
588: * case when a postcondition fails), then an exception was being thrown
589: * when the transaction was started again and the subject was reassociated
590: * with the Hibernate Session.
591: * <p/>
592: * Note: this is really a regression test.
593: *
594: * @throws Exception
595: */
596: public void testDirtySubjectAfterRollback() throws Exception {
597: System.out
598: .println("-------------------------- testDirtySubjectAfterRollback() begin ---");
599: final String userValue = "testDirtySubjectAfterRollback"
600: + Thread.currentThread().getName();
601: List activities = new LinkedList();
602:
603: final String activityName = "sync_failpostcondition";
604: activities.add(new DummySynchronousActivity(activityName) {
605: public void setController(Controller controller) {
606: super .setController(controller);
607: environment.put("activity.precondition", "x");
608: environment.put("activity.postcondition", "!x");
609: }
610:
611: public void execute(Object subject) {
612: // Dirty the subject by adding an enlistment.
613:
614: try {
615: controller.scheduleAnnouncement(userValue, 3600);
616: } catch (Exception e) {
617: e.printStackTrace();
618: fail("Unexpected exception: " + e);
619: }
620: }
621:
622: public int getTrials() {
623: return 2;
624: }
625:
626: public int getRetryDelay() {
627: return 3600;
628: }
629: });
630:
631: controller.setActivities(activities);
632: List conditions = new LinkedList();
633: conditions.add(new DummyCondition(activityName));
634: conditions.add(new DummyCondition("x"));
635:
636: controller.setConditions(conditions);
637:
638: controller.createSubject(userValue);
639:
640: try {
641: // The controller will attempt to execute the activity within a
642: // transaction, our activity will dirty the subject, the postcondition
643: // will fail, the Controller will rollback the transaction, start a
644: // new transaction, and attempt to reassociate the Subject instance it
645: // holds with the new transaction. At that point is when an exception
646: // was being thrown, and if it is now thrown, it shows the bug has
647: // crept back into the system.
648: controller.process(userValue);
649: } catch (Throwable t) {
650: t.printStackTrace();
651: fail("controller.process should not have thrown exception: "
652: + t);
653: }
654:
655: Subject subject = getSubject(userValue);
656: SortedSet enlistments = subject.getEnlistments();
657: System.out.println("subject.getLogs() = " + subject.getLogs());
658: System.out.println("subject.getEnlistments = " + enlistments);
659:
660: // We should have two enlistments: one from the scheduleAnnouncement
661: // made by our excute() method in our synchronous activity and one for the
662: // RETRY because our postcondition failed.
663: assertEquals(1, enlistments.size());
664: boolean foundRetry = false;
665: boolean foundEvaluate = false;
666: for (Iterator iterator = enlistments.iterator(); iterator
667: .hasNext();) {
668: Enlistment enlistment = (Enlistment) iterator.next();
669: if ("RETRY".equals(enlistment.getCommand())
670: && activityName.equals(enlistment.getActivity())) {
671: foundRetry = true;
672: } else if ("EVALUATE".equals(enlistment.getCommand())) {
673: foundEvaluate = true;
674: } else {
675: fail("Unexpected enlistment found for subject: "
676: + enlistment);
677: }
678:
679: assertTrue(System.currentTimeMillis() + 3600000 >= enlistment
680: .getTimeout());
681: assertTrue(System.currentTimeMillis() + 3500000 < enlistment
682: .getTimeout());
683: }
684:
685: assertTrue(foundRetry);
686: assertFalse(foundEvaluate);
687:
688: controller.destroySubject(userValue);
689: controller.timeout();
690: System.out
691: .println("-------------------------- testRollbackBecauseOfFailedPostcondition() end ---");
692: }
693:
694: // TODO: test for actors
695: }
|