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 com.tc.object.config.ConfigVisitor;
008: import com.tc.object.config.DSOClientConfigHelper;
009: import com.tc.object.config.TransparencyClassSpec;
010: import com.tc.simulator.app.ApplicationConfig;
011: import com.tc.simulator.listener.ListenerProvider;
012: import com.tctest.runner.AbstractErrorCatchingTransparentApp;
013:
014: import java.util.HashMap;
015: import java.util.Map;
016: import java.util.concurrent.CyclicBarrier;
017:
018: public class MutableInstrumentedEnumTest extends TransparentTestBase {
019:
020: private static final int NODE_COUNT = 3;
021:
022: public void doSetUp(TransparentTestIface t) throws Exception {
023: t.getTransparentAppConfig().setClientCount(NODE_COUNT);
024: t.initializeTestRunner();
025: }
026:
027: protected Class getApplicationClass() {
028: return MutableInstrumentedEnumTestApp.class;
029: }
030:
031: public static class MutableInstrumentedEnumTestApp extends
032: AbstractErrorCatchingTransparentApp {
033:
034: private final Map<String, Ref> mapRoot = new HashMap<String, Ref>();
035: private final CyclicBarrier barrier;
036:
037: public MutableInstrumentedEnumTestApp(String appId,
038: ApplicationConfig cfg, ListenerProvider listenerProvider) {
039: super (appId, cfg, listenerProvider);
040: barrier = new CyclicBarrier(getParticipantCount());
041: }
042:
043: protected void runTest() throws Throwable {
044:
045: int index = barrier.await();
046:
047: MutableEnum e = MutableEnum.THREE;
048:
049: if (index == 0) {
050: synchronized (mapRoot) {
051: mapRoot.put("e", new Ref(e));
052: }
053: }
054:
055: barrier.await();
056:
057: if (index == 0) {
058: synchronized (mapRoot) {
059: e.mutate();
060: }
061: }
062:
063: barrier.await();
064:
065: if (index != 0) {
066: // acquiring this lock should force the potentially bad TXN (containing the change to the shared mutable enum)
067: // to be flushed
068: synchronized (mapRoot) {
069: mapRoot.clear();
070: }
071: }
072:
073: barrier.await();
074:
075: }
076:
077: public static void visitL1DSOConfig(ConfigVisitor visitor,
078: DSOClientConfigHelper config) {
079: String testClass = MutableInstrumentedEnumTestApp.class
080: .getName();
081: TransparencyClassSpec spec = config
082: .getOrCreateSpec(testClass);
083:
084: config.getOrCreateSpec(MutableEnum.class.getName());
085: config.getOrCreateSpec(Ref.class.getName());
086:
087: String methodExpression = "* " + testClass + "*.*(..)";
088: config.addWriteAutolock(methodExpression);
089:
090: spec.addRoot("barrier", "barrier");
091: spec.addRoot("mapRoot", "mapRoot");
092: }
093:
094: }
095:
096: public enum MutableEnum {
097: ONE, TWO, THREE;
098:
099: private int mutableState;
100:
101: int mutate() {
102: return ++mutableState;
103: }
104: }
105:
106: private static class Ref {
107:
108: private final Object o;
109:
110: Ref(Object o) {
111: this .o = o;
112: }
113:
114: Object getO() {
115: return o;
116: }
117:
118: }
119:
120: }
|