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 EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;
008:
009: import com.tc.object.bytecode.Manageable;
010: import com.tc.object.config.ConfigVisitor;
011: import com.tc.object.config.DSOClientConfigHelper;
012: import com.tc.object.config.TransparencyClassSpec;
013: import com.tc.object.config.spec.CyclicBarrierSpec;
014: import com.tc.simulator.app.ApplicationConfig;
015: import com.tc.simulator.listener.ListenerProvider;
016: import com.tc.util.Assert;
017: import com.tctest.runner.AbstractErrorCatchingTransparentApp;
018:
019: import java.lang.reflect.Method;
020: import java.util.HashMap;
021: import java.util.Hashtable;
022: import java.util.Iterator;
023: import java.util.Map;
024: import java.util.Map.Entry;
025:
026: public class PartialCollectionsCloneTest extends TransparentTestBase {
027:
028: private static final int NODE_COUNT = 2;
029:
030: public void doSetUp(TransparentTestIface t) throws Exception {
031: t.getTransparentAppConfig().setClientCount(NODE_COUNT);
032: t.initializeTestRunner();
033: }
034:
035: protected Class getApplicationClass() {
036: return PartialCollectionsCloneTestApp.class;
037: }
038:
039: public static class PartialCollectionsCloneTestApp extends
040: AbstractErrorCatchingTransparentApp {
041: private static final int MAP_SIZE = 1000;
042: private final CyclicBarrier barrier;
043: private HashMap hashmap;
044: private Hashtable hashtable;
045:
046: public PartialCollectionsCloneTestApp(String appId,
047: ApplicationConfig cfg, ListenerProvider listenerProvider) {
048: super (appId, cfg, listenerProvider);
049: barrier = new CyclicBarrier(getParticipantCount());
050: }
051:
052: protected void runTest() throws Throwable {
053: boolean rootCreator = barrier.barrier() == 0;
054:
055: if (rootCreator) {
056: createRoots();
057: }
058:
059: barrier.barrier();
060:
061: if (!rootCreator) {
062: testMapClone(hashmap);
063: testMapClone(hashtable);
064: }
065:
066: barrier.barrier();
067: }
068:
069: private void testMapClone(Map m) {
070: final Map cloned;
071:
072: // read the map in the same lock under which is was mutated
073: synchronized (m) {
074: cloned = (Map) cloneIt(m);
075: }
076:
077: Assert.assertEquals(MAP_SIZE, cloned.size());
078:
079: if (((Manageable) cloned).__tc_isManaged()) {
080: throw new AssertionError("cloned object is shared");
081: }
082:
083: for (Iterator i = cloned.entrySet().iterator(); i.hasNext();) {
084: Map.Entry entry = (Entry) i.next();
085:
086: // Before the fix for clone() of partial maps, this would fail with ClassCastException since unresolved
087: // types are still in the map values
088: NonLiteralObject nlo = (NonLiteralObject) entry
089: .getValue();
090: Assert.assertNotNull(nlo);
091: }
092: }
093:
094: private Object cloneIt(Object o) {
095: try {
096: Method m = o.getClass().getDeclaredMethod("clone",
097: new Class[] {});
098: return m.invoke(o, new Object[] {});
099: } catch (Exception e) {
100: throw new RuntimeException(e);
101: }
102: }
103:
104: private void createRoots() {
105: hashmap = new HashMap();
106: hashtable = new Hashtable();
107:
108: populateMap(hashmap);
109: populateMap(hashtable);
110: }
111:
112: private void populateMap(Map m) {
113: synchronized (m) {
114: for (int i = 0; i < MAP_SIZE; i++) {
115: m.put(new Integer(i), new NonLiteralObject());
116: }
117: }
118: }
119:
120: private static class NonLiteralObject {
121: final NonLiteralObject next;
122:
123: public NonLiteralObject() {
124: next = new NonLiteralObject(1);
125: }
126:
127: private NonLiteralObject(int i) {
128: if (i < 3) {
129: next = new NonLiteralObject(++i);
130: } else {
131: next = null;
132: }
133: }
134: }
135:
136: public static void visitL1DSOConfig(ConfigVisitor visitor,
137: DSOClientConfigHelper config) {
138: new CyclicBarrierSpec().visit(visitor, config);
139: String testClass = PartialCollectionsCloneTestApp.class
140: .getName();
141: TransparencyClassSpec spec = config
142: .getOrCreateSpec(testClass);
143: String methodExpr = "* " + testClass + "*.*(..)";
144: config.addWriteAutolock(methodExpr);
145: config.addIncludePattern(testClass + "*");
146:
147: spec.addRoot("barrier", "barrier");
148: spec.addRoot("hashmap", "hashmap");
149: spec.addRoot("hashtable", "hashtable");
150: }
151:
152: }
153:
154: }
|