001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.transaction.memory;
018:
019: import java.util.HashMap;
020: import java.util.Map;
021:
022: import junit.framework.Test;
023: import junit.framework.TestSuite;
024:
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027:
028: import org.apache.commons.transaction.util.CommonsLoggingLogger;
029: import org.apache.commons.transaction.util.LoggerFacade;
030: import org.apache.commons.transaction.util.RendezvousBarrier;
031:
032: /**
033: * Tests for map wrapper.
034: *
035: * @version $Id: OptimisticMapWrapperTest.java 493628 2007-01-07 01:42:48Z joerg $
036: */
037: public class OptimisticMapWrapperTest extends MapWrapperTest {
038:
039: private static final Log log = LogFactory
040: .getLog(OptimisticMapWrapperTest.class.getName());
041: private static final LoggerFacade sLogger = new CommonsLoggingLogger(
042: log);
043:
044: public static Test suite() {
045: TestSuite suite = new TestSuite(OptimisticMapWrapperTest.class);
046: return suite;
047: }
048:
049: public static void main(java.lang.String[] args) {
050: junit.textui.TestRunner.run(suite());
051: }
052:
053: public OptimisticMapWrapperTest(String testName) {
054: super (testName);
055: }
056:
057: protected TransactionalMapWrapper getNewWrapper(Map map) {
058: return new OptimisticMapWrapper(map);
059: }
060:
061: // XXX no need for this code, just to make clear those tests are run as well
062: public void testBasic() throws Throwable {
063: super .testBasic();
064: }
065:
066: public void testComplex() throws Throwable {
067: super .testComplex();
068: }
069:
070: public void testSets() throws Throwable {
071: super .testSets();
072: }
073:
074: public void testMulti() throws Throwable {
075: log.info("Checking concurrent transaction features");
076:
077: final Map map1 = new HashMap();
078:
079: final OptimisticMapWrapper txMap1 = (OptimisticMapWrapper) getNewWrapper(map1);
080:
081: final RendezvousBarrier beforeCommitBarrier = new RendezvousBarrier(
082: "Before Commit", 2, BARRIER_TIMEOUT, sLogger);
083:
084: final RendezvousBarrier afterCommitBarrier = new RendezvousBarrier(
085: "After Commit", 2, BARRIER_TIMEOUT, sLogger);
086:
087: Thread thread1 = new Thread(new Runnable() {
088: public void run() {
089: txMap1.startTransaction();
090: try {
091: beforeCommitBarrier.meet();
092: txMap1.put("key1", "value2");
093: txMap1.commitTransaction();
094: afterCommitBarrier.call();
095: } catch (InterruptedException e) {
096: sLogger.logWarning("Thread interrupted", e);
097: afterCommitBarrier.reset();
098: beforeCommitBarrier.reset();
099: }
100: }
101: }, "Thread1");
102:
103: txMap1.put("key1", "value1");
104:
105: txMap1.startTransaction();
106: thread1.start();
107:
108: report("value1", (String) txMap1.get("key1"));
109: beforeCommitBarrier.call();
110: afterCommitBarrier.meet();
111: // we have serializable as isolation level, that's why I will still see the old value
112: report("value1", (String) txMap1.get("key1"));
113:
114: // now when I override it it should of course be my value
115: txMap1.put("key1", "value3");
116: report("value3", (String) txMap1.get("key1"));
117:
118: // after rollback it must be the value written by the other thread
119: txMap1.rollbackTransaction();
120: report("value2", (String) txMap1.get("key1"));
121: }
122:
123: public void testConflict() throws Throwable {
124: log.info("Checking concurrent transaction features");
125:
126: final Map map1 = new HashMap();
127:
128: final OptimisticMapWrapper txMap1 = (OptimisticMapWrapper) getNewWrapper(map1);
129:
130: final RendezvousBarrier beforeCommitBarrier = new RendezvousBarrier(
131: "Before Commit", 2, BARRIER_TIMEOUT, sLogger);
132:
133: final RendezvousBarrier afterCommitBarrier = new RendezvousBarrier(
134: "After Commit", 2, BARRIER_TIMEOUT, sLogger);
135:
136: Thread thread1 = new Thread(new Runnable() {
137: public void run() {
138: txMap1.startTransaction();
139: try {
140: beforeCommitBarrier.meet();
141: txMap1.put("key1", "value2");
142: txMap1.commitTransaction();
143: afterCommitBarrier.call();
144: } catch (InterruptedException e) {
145: sLogger.logWarning("Thread interrupted", e);
146: afterCommitBarrier.reset();
147: beforeCommitBarrier.reset();
148: }
149: }
150: }, "Thread1");
151:
152: txMap1.put("key1", "value1");
153:
154: txMap1.startTransaction();
155: thread1.start();
156:
157: report("value1", (String) txMap1.get("key1"));
158: beforeCommitBarrier.call();
159: afterCommitBarrier.meet();
160: // we have serializable as isolation level, that's why I will still see the old value
161: report("value1", (String) txMap1.get("key1"));
162:
163: // now when I override it it should of course be my value
164: txMap1.put("key1", "value3");
165: report("value3", (String) txMap1.get("key1"));
166:
167: boolean conflict = false;
168:
169: try {
170: txMap1.commitTransaction();
171: } catch (ConflictException ce) {
172: conflict = true;
173: }
174: assertTrue(conflict);
175: // after failed commit it must be the value written by the other thread
176: report("value2", (String) map1.get("key1"));
177:
178: // force commit anyhow...
179: txMap1.commitTransaction(true);
180: // after successful commit it must be the value written by this thread
181: report("value3", (String) txMap1.get("key1"));
182: report("value3", (String) map1.get("key1"));
183: }
184:
185: public void testTxControl() throws Throwable {
186: super.testTxControl();
187: }
188:
189: }
|