1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.transaction.memory;
18
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23
24 import javax.transaction.Status;
25
26 import junit.framework.Test;
27 import junit.framework.TestCase;
28 import junit.framework.TestSuite;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 import org.apache.commons.transaction.util.CommonsLoggingLogger;
34 import org.apache.commons.transaction.util.LoggerFacade;
35 import org.apache.commons.transaction.util.RendezvousBarrier;
36
37
38
39
40
41
42 public class MapWrapperTest extends TestCase {
43
44 private static final Log log = LogFactory.getLog(MapWrapperTest.class.getName());
45 private static final LoggerFacade sLogger = new CommonsLoggingLogger(log);
46
47 protected static final long BARRIER_TIMEOUT = 20000;
48
49
50 protected static void report(String should, String is) {
51 if (!should.equals(is)) {
52 fail("\nWrong output:\n'" + is + "'\nShould be:\n'" + should + "'\n");
53 }
54 }
55
56 protected static void checkCollection(Collection col, Object[] values) {
57 int cnt = 0;
58 int trueCnt = 0;
59
60 for (Iterator it = col.iterator(); it.hasNext();) {
61 cnt++;
62 Object value1 = it.next();
63 for (int i = 0; i < values.length; i++) {
64 Object value2 = values[i];
65 if (value2.equals(value1))
66 trueCnt++;
67 }
68 }
69 assertEquals(cnt, values.length);
70 assertEquals(trueCnt, values.length);
71 }
72
73 public static Test suite() {
74 TestSuite suite = new TestSuite(MapWrapperTest.class);
75 return suite;
76 }
77
78 public static void main(java.lang.String[] args) {
79 junit.textui.TestRunner.run(suite());
80 }
81
82 public MapWrapperTest(String testName) {
83 super(testName);
84 }
85
86 protected TransactionalMapWrapper getNewWrapper(Map map) {
87 return new TransactionalMapWrapper(map);
88 }
89
90 public void testBasic() throws Throwable {
91
92 sLogger.logInfo("Checking basic transaction features");
93
94 final Map map1 = new HashMap();
95
96 final TransactionalMapWrapper txMap1 = getNewWrapper(map1);
97
98 assertTrue(txMap1.isEmpty());
99
100
101 txMap1.put("key1", "value1");
102 report("value1", (String) map1.get("key1"));
103 assertFalse(txMap1.isEmpty());
104
105
106 txMap1.startTransaction();
107 assertFalse(txMap1.isEmpty());
108 txMap1.put("key1", "value2");
109 report("value1", (String) map1.get("key1"));
110 report("value2", (String) txMap1.get("key1"));
111 txMap1.commitTransaction();
112 report("value2", (String) map1.get("key1"));
113 report("value2", (String) txMap1.get("key1"));
114
115
116 txMap1.startTransaction();
117 txMap1.put("key1", "value3");
118 txMap1.rollbackTransaction();
119 report("value2", (String) map1.get("key1"));
120 report("value2", (String) txMap1.get("key1"));
121 }
122
123 public void testContainsKeyWithNullValue() throws Throwable {
124
125 sLogger.logInfo("Checking containsKey returns true when the value is null");
126
127 final Map map1 = new HashMap();
128
129 final TransactionalMapWrapper txMap1 = getNewWrapper(map1);
130
131 assertTrue(txMap1.isEmpty());
132
133
134 txMap1.put("key1", null);
135 assertTrue(txMap1.containsKey("key1"));
136
137
138 txMap1.startTransaction();
139 txMap1.put("key2", null);
140 assertTrue(txMap1.containsKey("key2"));
141 txMap1.remove("key1");
142 assertTrue(map1.containsKey("key1"));
143 txMap1.commitTransaction();
144 assertTrue(txMap1.containsKey("key2"));
145 assertFalse(txMap1.containsKey("key1"));
146
147 txMap1.startTransaction();
148 assertTrue(txMap1.containsKey("key2"));
149 txMap1.remove("key2");
150 assertFalse(txMap1.containsKey("key2"));
151 txMap1.commitTransaction();
152 }
153
154 public void testComplex() throws Throwable {
155
156 sLogger.logInfo("Checking advanced and complex transaction features");
157
158 final Map map1 = new HashMap();
159
160 final TransactionalMapWrapper txMap1 = getNewWrapper(map1);
161
162
163 txMap1.put("key1", "value1");
164 txMap1.put("key2", "value2");
165
166
167 sLogger.logInfo("Checking if global values are present");
168
169 assertTrue(txMap1.containsValue("value1"));
170 assertTrue(txMap1.containsValue("value2"));
171 assertFalse(txMap1.containsValue("novalue"));
172
173
174 sLogger.logInfo("Checking if global keys are present");
175 assertTrue(txMap1.containsKey("key1"));
176 assertTrue(txMap1.containsKey("key2"));
177 assertFalse(txMap1.containsKey("nokey"));
178
179
180 txMap1.startTransaction();
181 txMap1.put("key3", "value3");
182 txMap1.put("key4", "value4");
183
184
185 sLogger.logInfo("Checking if values inside transactions are present");
186 assertTrue(txMap1.containsValue("value1"));
187 assertTrue(txMap1.containsValue("value2"));
188 assertTrue(txMap1.containsValue("value3"));
189 assertTrue(txMap1.containsValue("value4"));
190 assertFalse(txMap1.containsValue("novalue"));
191
192
193 sLogger.logInfo("Checking if keys inside transactions are present");
194 assertTrue(txMap1.containsKey("key1"));
195 assertTrue(txMap1.containsKey("key2"));
196 assertTrue(txMap1.containsKey("key3"));
197 assertTrue(txMap1.containsKey("key4"));
198 assertFalse(txMap1.containsKey("nokey"));
199
200
201 sLogger.logInfo("Checking remove inside transactions");
202 txMap1.remove("key1");
203 assertFalse(txMap1.containsKey("key1"));
204 assertFalse(txMap1.containsValue("value1"));
205 assertNull(txMap1.get("key1"));
206 assertEquals(3, txMap1.size());
207
208
209 txMap1.remove("key3");
210 assertFalse(txMap1.containsKey("key3"));
211 assertFalse(txMap1.containsValue("value3"));
212 assertNull(txMap1.get("key3"));
213 assertEquals(2, txMap1.size());
214
215 sLogger.logInfo("Checking remove and propagation after commit");
216 txMap1.commitTransaction();
217
218 txMap1.remove("key1");
219 assertFalse(txMap1.containsKey("key1"));
220 assertFalse(txMap1.containsValue("value1"));
221 assertNull(txMap1.get("key1"));
222 assertFalse(txMap1.containsKey("key3"));
223 assertFalse(txMap1.containsValue("value3"));
224 assertNull(txMap1.get("key3"));
225 assertEquals(2, txMap1.size());
226 }
227
228 public void testSets() throws Throwable {
229
230 sLogger.logInfo("Checking set opertaions");
231
232 final Map map1 = new HashMap();
233
234 final TransactionalMapWrapper txMap1 = getNewWrapper(map1);
235
236
237 txMap1.put("key1", "value1");
238 txMap1.put("key2", "value200");
239
240
241 txMap1.startTransaction();
242 txMap1.put("key2", "value2");
243 txMap1.put("key3", "value3");
244 txMap1.put("key4", "value4");
245
246
247 boolean key1P, key2P, key3P, key4P;
248 key1P = key2P = key3P = key4P = false;
249 int cnt = 0;
250 for (Iterator it = txMap1.entrySet().iterator(); it.hasNext();) {
251 cnt++;
252 Map.Entry entry = (Map.Entry) it.next();
253 if (entry.getKey().equals("key1") && entry.getValue().equals("value1"))
254 key1P = true;
255 else if (entry.getKey().equals("key2") && entry.getValue().equals("value2"))
256 key2P = true;
257 else if (entry.getKey().equals("key3") && entry.getValue().equals("value3"))
258 key3P = true;
259 else if (entry.getKey().equals("key4") && entry.getValue().equals("value4"))
260 key4P = true;
261 }
262 assertEquals(cnt, 4);
263 assertTrue(key1P && key2P && key3P && key4P);
264
265 checkCollection(txMap1.values(), new String[] { "value1", "value2", "value3", "value4" });
266 checkCollection(txMap1.keySet(), new String[] { "key1", "key2", "key3", "key4" });
267
268 txMap1.commitTransaction();
269
270
271 key1P = key2P = key3P = key4P = false;
272 cnt = 0;
273 for (Iterator it = txMap1.entrySet().iterator(); it.hasNext();) {
274 cnt++;
275 Map.Entry entry = (Map.Entry) it.next();
276 if (entry.getKey().equals("key1") && entry.getValue().equals("value1"))
277 key1P = true;
278 else if (entry.getKey().equals("key2") && entry.getValue().equals("value2"))
279 key2P = true;
280 else if (entry.getKey().equals("key3") && entry.getValue().equals("value3"))
281 key3P = true;
282 else if (entry.getKey().equals("key4") && entry.getValue().equals("value4"))
283 key4P = true;
284 }
285 assertEquals(cnt, 4);
286 assertTrue(key1P && key2P && key3P && key4P);
287
288 checkCollection(txMap1.values(), new String[] { "value1", "value2", "value3", "value4" });
289 checkCollection(txMap1.keySet(), new String[] { "key1", "key2", "key3", "key4" });
290
291
292
293 txMap1.startTransaction();
294
295
296 txMap1.put("key5", "value5");
297
298 txMap1.put("key4", "value400");
299
300 txMap1.remove("key1");
301
302 assertEquals(txMap1.size(), 4);
303
304 txMap1.clear();
305 assertEquals(txMap1.size(), 0);
306 assertEquals(map1.size(), 4);
307
308
309 txMap1.put("key5", "value5");
310
311 txMap1.remove("key1");
312
313
314 assertEquals(txMap1.size(), 1);
315 assertEquals(map1.size(), 4);
316 assertNull(txMap1.get("key4"));
317 assertNotNull(txMap1.get("key5"));
318
319 txMap1.commitTransaction();
320
321
322 assertEquals(txMap1.size(), 1);
323 assertEquals(map1.size(), 1);
324 assertNull(txMap1.get("key4"));
325 assertNotNull(txMap1.get("key5"));
326 assertNull(map1.get("key4"));
327 assertNotNull(map1.get("key5"));
328 }
329
330 public void testMulti() throws Throwable {
331 sLogger.logInfo("Checking concurrent transaction features");
332
333 final Map map1 = new HashMap();
334
335 final TransactionalMapWrapper txMap1 = getNewWrapper(map1);
336
337 final RendezvousBarrier beforeCommitBarrier =
338 new RendezvousBarrier("Before Commit", 2, BARRIER_TIMEOUT, sLogger);
339
340 final RendezvousBarrier afterCommitBarrier = new RendezvousBarrier("After Commit", 2, BARRIER_TIMEOUT, sLogger);
341
342 Thread thread1 = new Thread(new Runnable() {
343 public void run() {
344 txMap1.startTransaction();
345 try {
346 beforeCommitBarrier.meet();
347 txMap1.put("key1", "value2");
348 txMap1.commitTransaction();
349 afterCommitBarrier.call();
350 } catch (InterruptedException e) {
351 sLogger.logWarning("Thread interrupted", e);
352 afterCommitBarrier.reset();
353 beforeCommitBarrier.reset();
354 }
355 }
356 }, "Thread1");
357
358 txMap1.put("key1", "value1");
359
360 txMap1.startTransaction();
361 thread1.start();
362
363 report("value1", (String) txMap1.get("key1"));
364 beforeCommitBarrier.call();
365 afterCommitBarrier.meet();
366
367 report("value2", (String) txMap1.get("key1"));
368
369
370 txMap1.put("key1", "value3");
371 report("value3", (String) txMap1.get("key1"));
372
373
374 txMap1.rollbackTransaction();
375 report("value2", (String) txMap1.get("key1"));
376 }
377
378 public void testTxControl() throws Throwable {
379 sLogger.logInfo("Checking advanced transaction control (heavily used in JCA implementation)");
380
381 final Map map1 = new HashMap();
382
383 final TransactionalMapWrapper txMap1 = getNewWrapper(map1);
384
385 assertEquals(txMap1.getTransactionState(), Status.STATUS_NO_TRANSACTION);
386 txMap1.startTransaction();
387 assertEquals(txMap1.getTransactionState(), Status.STATUS_ACTIVE);
388
389 assertTrue(txMap1.isReadOnly());
390 txMap1.put("key", "value");
391 assertFalse(txMap1.isReadOnly());
392
393 assertFalse(txMap1.isTransactionMarkedForRollback());
394 txMap1.markTransactionForRollback();
395 assertTrue(txMap1.isTransactionMarkedForRollback());
396
397 boolean failed = false;
398 try {
399 txMap1.commitTransaction();
400 } catch (IllegalStateException ise) {
401 failed = true;
402 }
403 assertTrue(failed);
404 txMap1.rollbackTransaction();
405 assertEquals(txMap1.getTransactionState(), Status.STATUS_NO_TRANSACTION);
406
407 txMap1.startTransaction();
408 final TransactionalMapWrapper.TxContext ctx = txMap1.suspendTransaction();
409 final RendezvousBarrier afterSuspendBarrier =
410 new RendezvousBarrier("After Suspend", 2, BARRIER_TIMEOUT, sLogger);
411
412 new Thread(new Runnable() {
413 public void run() {
414 txMap1.resumeTransaction(ctx);
415 txMap1.put("key2", "value2");
416 txMap1.suspendTransaction();
417 afterSuspendBarrier.call();
418 }
419 }).start();
420
421 afterSuspendBarrier.meet();
422 txMap1.resumeTransaction(ctx);
423
424 assertEquals(txMap1.size(), 1);
425 txMap1.put("key3", "value3");
426 assertEquals(txMap1.size(), 2);
427 assertEquals(map1.size(), 0);
428
429 txMap1.commitTransaction();
430 assertEquals(txMap1.size(), 2);
431 assertEquals(map1.size(), 2);
432 }
433
434 }