001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tctest;
006:
007: import org.apache.commons.collections.FastHashMap;
008:
009: import com.tc.object.config.ConfigVisitor;
010: import com.tc.object.config.DSOClientConfigHelper;
011: import com.tc.object.config.TransparencyClassSpec;
012: import com.tc.simulator.app.ApplicationConfig;
013: import com.tc.simulator.listener.ListenerProvider;
014: import com.tc.util.Assert;
015: import com.tc.util.TIMUtil;
016:
017: import gnu.trove.THashMap;
018:
019: import java.net.Socket;
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.HashMap;
023: import java.util.Hashtable;
024: import java.util.Iterator;
025: import java.util.LinkedHashMap;
026: import java.util.List;
027: import java.util.Map;
028: import java.util.Set;
029: import java.util.TreeMap;
030: import java.util.concurrent.ConcurrentHashMap;
031: import java.util.concurrent.CyclicBarrier;
032:
033: /**
034: * Test to make sure local object state is preserved when TC throws:
035: *
036: * UnlockedSharedObjectException ReadOnlyException TCNonPortableObjectError
037: *
038: * Map version
039: *
040: * INT-186
041: *
042: * @author hhuynh
043: */
044: public class MapLocalStateTestApp extends GenericLocalStateTestApp {
045: private List<Wrapper> root = new ArrayList<Wrapper>();
046: private CyclicBarrier barrier;
047: private Class[] mapClasses = new Class[] { THashMap.class,
048: TreeMap.class, LinkedHashMap.class, Hashtable.class,
049: HashMap.class, ConcurrentHashMap.class, FastHashMap.class };
050:
051: public MapLocalStateTestApp(String appId, ApplicationConfig cfg,
052: ListenerProvider listenerProvider) {
053: super (appId, cfg, listenerProvider);
054: barrier = new CyclicBarrier(cfg.getGlobalParticipantCount());
055: }
056:
057: protected void runTest() throws Throwable {
058: if (await() == 0) {
059: createMaps();
060: }
061: await();
062:
063: for (LockMode lockMode : LockMode.values()) {
064: for (Wrapper mw : root) {
065: testMutate(mw, lockMode, new PutMutator());
066: testMutate(mw, lockMode, new PutAllMutator());
067: testMutate(mw, lockMode, new RemoveMutator());
068: testMutate(mw, lockMode, new ClearMutator());
069: testMutate(mw, lockMode, new KeySetClearMutator());
070: testMutate(mw, lockMode, new RemoveValueMutator());
071: testMutate(mw, lockMode, new EntrySetClearMutator());
072: testMutate(mw, lockMode,
073: new EntrySetIteratorRemoveMutator());
074: testMutate(mw, lockMode,
075: new KeySetIteratorRemoveMutator());
076: testMutate(mw, lockMode,
077: new ValuesIteratorRemoveMutator());
078: testMutate(mw, lockMode, new KeySetRemoveMutator());
079: testMutate(mw, lockMode, new AddEntryMutator());
080: testMutate(mw, lockMode,
081: new AddNonPortableEntryMutator());
082: // Failing, disabled for now
083: // testMutate(w, LockMode.WRITE, new NonPortableAddMutator());
084: }
085: }
086:
087: }
088:
089: private void createMaps() throws Exception {
090: Map data = new HashMap();
091: data.put("k1", "v1");
092: data.put("k2", "v2");
093: data.put("k3", "v3");
094:
095: synchronized (root) {
096: for (Class k : mapClasses) {
097: CollectionWrapper mw = new CollectionWrapper(k,
098: Map.class);
099: ((Map) mw.getObject()).putAll(data);
100: root.add(mw);
101: }
102: }
103: }
104:
105: protected void validate(int oldSize, Wrapper wrapper,
106: LockMode lockMode, Mutator mutator) throws Throwable {
107: int newSize = wrapper.size();
108: switch (lockMode) {
109: case NONE:
110: case READ:
111: Assert.assertEquals("Type: "
112: + wrapper.getObject().getClass() + ", lock: "
113: + lockMode, oldSize, newSize);
114: if (mutator instanceof AddEntryMutator) {
115: Collection values = ((Map) wrapper.getObject())
116: .values();
117: for (Iterator it = values.iterator(); it.hasNext();) {
118: String value = (String) it.next();
119: Assert.assertFalse("Type: "
120: + wrapper.getObject().getClass()
121: + ", lock: " + lockMode, value
122: .equals("hung"));
123: }
124: } else if (mutator instanceof NonPortableAddMutator) {
125: Collection values = ((Map) wrapper.getObject())
126: .values();
127: for (Iterator it = values.iterator(); it.hasNext();) {
128: Object value = it.next();
129: Assert.assertFalse("Type: "
130: + wrapper.getObject().getClass()
131: + ", lock: " + lockMode,
132: value instanceof Socket);
133: }
134: }
135: break;
136: case WRITE:
137: System.out.println("Map type: "
138: + wrapper.getObject().getClass().getName());
139: System.out.println("Current size: " + newSize);
140: System.out.println("New size: " + newSize);
141: Assert.assertFalse("Type: "
142: + wrapper.getObject().getClass()
143: + ", socket shouldn't be added", ((Map) wrapper
144: .getObject()).containsKey("socket"));
145: break;
146: default:
147: throw new RuntimeException("Shouldn't happen");
148: }
149: }
150:
151: protected int await() {
152: try {
153: return barrier.await();
154: } catch (Exception e) {
155: throw new RuntimeException(e);
156: }
157: }
158:
159: public static void visitL1DSOConfig(ConfigVisitor visitor,
160: DSOClientConfigHelper config) {
161: config.addModule(TIMUtil.COMMONS_COLLECTIONS_3_1, TIMUtil
162: .getVersion(TIMUtil.COMMONS_COLLECTIONS_3_1));
163:
164: String testClass = MapLocalStateTestApp.class.getName();
165: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
166:
167: config.addIncludePattern(testClass + "$*");
168: config.addIncludePattern(GenericLocalStateTestApp.class
169: .getName()
170: + "$*");
171:
172: config.addWriteAutolock("* " + testClass + "*.createMaps()");
173: config.addWriteAutolock("* " + testClass + "*.validate()");
174: config.addReadAutolock("* " + testClass + "*.runTest()");
175:
176: spec.addRoot("root", "root");
177: spec.addRoot("barrier", "barrier");
178:
179: config.addReadAutolock("* " + Handler.class.getName()
180: + "*.invokeWithReadLock(..)");
181: config.addWriteAutolock("* " + Handler.class.getName()
182: + "*.invokeWithWriteLock(..)");
183: config.addWriteAutolock("* " + Handler.class.getName()
184: + "*.setLockMode(..)");
185: }
186:
187: private static class PutMutator implements Mutator {
188: public void doMutate(Object o) {
189: Map map = (Map) o;
190: map.put("key", "value");
191: }
192: }
193:
194: private static class PutAllMutator implements Mutator {
195: public void doMutate(Object o) {
196: Map map = (Map) o;
197: Map anotherMap = new HashMap();
198: anotherMap.put("k", "v");
199: map.putAll(anotherMap);
200: }
201: }
202:
203: private static class RemoveMutator implements Mutator {
204: public void doMutate(Object o) {
205: Map map = (Map) o;
206: map.remove("k1");
207: }
208: }
209:
210: private static class ClearMutator implements Mutator {
211: public void doMutate(Object o) {
212: Map map = (Map) o;
213: map.clear();
214: }
215: }
216:
217: private static class RemoveValueMutator implements Mutator {
218: public void doMutate(Object o) {
219: Map map = (Map) o;
220: Collection values = map.values();
221: values.remove("v1");
222: }
223: }
224:
225: private static class EntrySetClearMutator implements Mutator {
226: public void doMutate(Object o) {
227: Map map = (Map) o;
228: Set entries = map.entrySet();
229: entries.clear();
230: }
231: }
232:
233: private static class AddEntryMutator implements Mutator {
234: public void doMutate(Object o) {
235: Map map = (Map) o;
236: Set entries = map.entrySet();
237: for (Iterator it = entries.iterator(); it.hasNext();) {
238: Map.Entry entry = (Map.Entry) it.next();
239: entry.setValue("hung");
240: }
241: }
242: }
243:
244: private static class AddNonPortableEntryMutator implements Mutator {
245: public void doMutate(Object o) {
246: Map map = (Map) o;
247: Set entries = map.entrySet();
248: for (Iterator it = entries.iterator(); it.hasNext();) {
249: Map.Entry entry = (Map.Entry) it.next();
250: entry.setValue(new Socket());
251: }
252: }
253: }
254:
255: private static class EntrySetIteratorRemoveMutator implements
256: Mutator {
257: public void doMutate(Object o) {
258: Map map = (Map) o;
259: Set entries = map.entrySet();
260: for (Iterator it = entries.iterator(); it.hasNext();) {
261: it.next();
262: it.remove();
263: }
264: }
265: }
266:
267: private static class KeySetClearMutator implements Mutator {
268: public void doMutate(Object o) {
269: Map map = (Map) o;
270: Set keys = map.keySet();
271: keys.clear();
272: }
273: }
274:
275: private static class KeySetIteratorRemoveMutator implements Mutator {
276: public void doMutate(Object o) {
277: Map map = (Map) o;
278: Set keys = map.keySet();
279: for (Iterator it = keys.iterator(); it.hasNext();) {
280: it.next();
281: it.remove();
282: }
283: }
284: }
285:
286: private static class ValuesIteratorRemoveMutator implements Mutator {
287: public void doMutate(Object o) {
288: Map map = (Map) o;
289: Collection values = map.values();
290: for (Iterator it = values.iterator(); it.hasNext();) {
291: it.next();
292: it.remove();
293: }
294: }
295: }
296:
297: private static class KeySetRemoveMutator implements Mutator {
298: public void doMutate(Object o) {
299: Map map = (Map) o;
300: Set keys = map.keySet();
301: keys.remove("k1");
302: }
303: }
304:
305: private static class NonPortableAddMutator implements Mutator {
306: public void doMutate(Object o) {
307: Map map = (Map) o;
308: Map anotherMap = new LinkedHashMap();
309: anotherMap.put("k4", "v4");
310: anotherMap.put("k5", "v5");
311: anotherMap.put("k6", "v6");
312: anotherMap.put("k7", "v7");
313: anotherMap.put("k8", "v8");
314: anotherMap.put("k9", "v9");
315: anotherMap.put("socket", new Socket());
316: anotherMap.put("k10", "v10");
317: map.putAll(anotherMap);
318: }
319: }
320: }
|