1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.routeheader;
17
18 import org.junit.Test;
19 import org.kuali.rice.kew.api.KewApiConstants;
20 import org.kuali.rice.kew.api.WorkflowDocument;
21 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
22 import org.kuali.rice.kew.doctype.bo.DocumentType;
23 import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
24 import org.kuali.rice.kew.service.KEWServiceLocator;
25 import org.kuali.rice.kew.test.KEWTestCase;
26 import org.kuali.rice.test.BaselineTestCase;
27 import org.springframework.transaction.TransactionStatus;
28 import org.springframework.transaction.support.TransactionCallback;
29
30 import java.sql.Timestamp;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.TimeUnit;
33
34 import static org.junit.Assert.*;
35
36 @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.NONE)
37 public class RouteHeaderServiceTest extends KEWTestCase {
38
39 private RouteHeaderService routeHeaderService;
40
41 protected void setUpAfterDataLoad() throws Exception {
42 super.setUpAfterDataLoad();
43 routeHeaderService = KEWServiceLocator.getRouteHeaderService();
44 }
45
46
47
48
49
50
51
52 @Test
53 public void testLargeDocumentContent() throws Exception {
54 StringBuffer buffer = new StringBuffer();
55 buffer.append("<content>");
56 for (int index = 0; index < 10000; index++) {
57 buffer.append("abcdefghijklmnopqrstuvwxyz");
58 }
59 buffer.append("</content>");
60 DocumentRouteHeaderValue document = new DocumentRouteHeaderValue();
61 document.setDocContent(buffer.toString());
62 document.setDocRouteStatus(KewApiConstants.ROUTE_HEADER_INITIATED_CD);
63 document.setDocRouteLevel(0);
64 document.setDateModified(new Timestamp(System.currentTimeMillis()));
65 document.setCreateDate(new Timestamp(System.currentTimeMillis()));
66 document.setInitiatorWorkflowId("1");
67 DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName("TestDocumentType");
68 assertNotNull(documentType);
69 document.setDocumentTypeId(documentType.getDocumentTypeId());
70 document = routeHeaderService.saveRouteHeader(document);
71 assertNotNull("Document was saved, it should have an ID now.", document.getDocumentId());
72
73
74 document = routeHeaderService.getRouteHeader(document.getDocumentId());
75 String docContent = document.getDocContent();
76 assertEquals("Doc content should be the same size as original string buffer.", buffer.length(), docContent.length());
77 assertTrue("Should be greater than about 5000 bytes.", docContent.getBytes().length > 5000);
78 }
79
80 @Test public void testGetApplicationIdByDocumentId() throws Exception {
81 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "TestDocumentType2");
82 String documentId = document.getDocumentId();
83 String applicationId = routeHeaderService.getApplicationIdByDocumentId(documentId);
84 assertEquals("applicationId should be KEWNEW", "KEWNEW", applicationId);
85
86
87 document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "TestDocumentType");
88 documentId = document.getDocumentId();
89 applicationId = routeHeaderService.getApplicationIdByDocumentId(documentId);
90 assertEquals("applicationId should be KUALI", "KUALI", applicationId);
91 }
92
93 @Test public void testLockRouteHeader() throws Exception {
94
95 long timeout = 60 * 1000;
96
97 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "TestDocumentType");
98 document.saveDocumentData();
99 String documentId = document.getDocumentId();
100
101 final Locker locker1 = new Locker(documentId);
102 locker1.start();
103 locker1.latch1.await(timeout, TimeUnit.MILLISECONDS);
104
105
106 assertTrue(locker1.waiting);
107 assertFalse(locker1.completed);
108
109
110
111 final Locker locker2 = new Locker(documentId);
112 locker2.start();
113
114
115
116 Thread.sleep(2000);
117
118
119 assertTrue(locker2.prelock);
120 assertFalse(locker2.waiting);
121
122
123 locker1.latch2.countDown();
124 locker1.join(timeout);
125
126
127 assertTrue(locker1.completed);
128
129
130 Thread.sleep(2000);
131 locker2.latch2.countDown();
132 locker2.join(timeout);
133
134
135 assertTrue(locker2.completed);
136
137 }
138
139 private class Locker extends Thread {
140
141 private static final long TIMEOUT = 60 * 1000;
142
143 String documentId;
144 CountDownLatch latch1;
145 CountDownLatch latch2;
146
147 volatile boolean prelock;
148 volatile boolean waiting;
149 volatile boolean completed;
150
151 Locker(String documentId) {
152 this.documentId = documentId;
153 this.latch1 = new CountDownLatch(1);
154 this.latch2 = new CountDownLatch(1);
155 }
156
157 public void run() {
158 getTransactionTemplate().execute(new TransactionCallback() {
159 public Object doInTransaction(TransactionStatus status) {
160 prelock = true;
161 routeHeaderService.lockRouteHeader(documentId);
162 try {
163 waiting = true;
164 latch1.countDown();
165 latch2.await(TIMEOUT, TimeUnit.MILLISECONDS);
166 } catch (InterruptedException e) {
167 throw new RuntimeException("Shouldn't have been interrupted but was.", e);
168 }
169 return null;
170 }
171 });
172 completed = true;
173 }
174 }
175
176 }