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.asm.ClassAdapter;
010: import com.tc.asm.ClassVisitor;
011: import com.tc.asm.MethodVisitor;
012: import com.tc.asm.Opcodes;
013: import com.tc.exception.TCNonPortableObjectError;
014: import com.tc.object.bytecode.ClassAdapterFactory;
015: import com.tc.object.config.ConfigVisitor;
016: import com.tc.object.config.DSOClientConfigHelper;
017: import com.tc.object.config.TransparencyClassSpec;
018: import com.tc.object.config.spec.CyclicBarrierSpec;
019: import com.tc.simulator.app.ApplicationConfig;
020: import com.tc.simulator.listener.ListenerProvider;
021: import com.tc.util.Assert;
022: import com.tctest.runner.AbstractErrorCatchingTransparentApp;
023:
024: import java.util.HashMap;
025: import java.util.Map;
026:
027: /**
028: * Test to make sure custom adapted class and its inherited classes can be shared under DSO
029: *
030: * @author hhuynh
031: */
032: public class CustomClassAdapterTestApp extends
033: AbstractErrorCatchingTransparentApp {
034: private Map root = new HashMap();
035: private CyclicBarrier barrier;
036:
037: public CustomClassAdapterTestApp(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: Foo foo = new Foo();
045: Assert.assertEquals(-1, foo.getVal());
046: Assert.assertEquals(0, foo.getRealVal());
047: foo.setVal(100);
048: Assert.assertEquals(-1, foo.getVal());
049: Assert.assertEquals(100, foo.getRealVal());
050:
051: FooKid fooKid = new FooKid();
052: fooKid.setVal(100);
053: Assert.assertEquals(-1, fooKid.getVal());
054: Assert.assertEquals(-2, fooKid.getDoubleVal());
055:
056: if (barrier.barrier() == 0) {
057: synchronized (root) {
058: foo.setVal(200);
059: fooKid.setVal(200);
060: root.put("foo", foo);
061: root.put("fooKid", fooKid);
062: }
063: }
064:
065: barrier.barrier();
066: Foo sharedFoo = (Foo) root.get("foo");
067: Assert.assertEquals(-1, foo.getVal());
068: Assert.assertEquals(200, sharedFoo.getRealVal());
069:
070: FooKid sharedFooKid = (FooKid) root.get("fooKid");
071: Assert.assertEquals(-1, fooKid.getVal());
072: Assert.assertEquals(-2, sharedFooKid.getDoubleVal());
073:
074: // also make sure a class that happens to have a custom adapter isn't also
075: // portable (ie. it must be included to be portable)
076: AdaptedButNotIncluded a = new AdaptedButNotIncluded();
077: Assert.assertEquals(-1, a.getVal()); // tests that adaption did happen
078: try {
079: synchronized (root) {
080: root.put("test", new AdaptedButNotIncluded());
081: }
082: throw new AssertionError("Type is portable");
083: } catch (TCNonPortableObjectError e) {
084: // expected
085: }
086: }
087:
088: public static void visitL1DSOConfig(ConfigVisitor visitor,
089: DSOClientConfigHelper config) {
090: CyclicBarrierSpec cbspec = new CyclicBarrierSpec();
091: cbspec.visit(visitor, config);
092:
093: String testClass = CustomClassAdapterTestApp.class.getName();
094: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
095:
096: String methodExpression = "* " + testClass + "*.*(..)";
097: config.addWriteAutolock(methodExpression);
098: spec.addRoot("root", "root");
099: spec.addRoot("barrier", "barrier");
100:
101: config.addIncludePattern(Foo.class.getName());
102: config.addIncludePattern(FooKid.class.getName());
103: config.addCustomAdapter(Foo.class.getName(),
104: new GetValAdapter());
105:
106: config.addCustomAdapter(AdaptedButNotIncluded.class.getName(),
107: new GetValAdapter());
108: }
109:
110: }
111:
112: class AdaptedButNotIncluded {
113: private int val;
114:
115: public int getVal() {
116: return val;
117: }
118: }
119:
120: class Foo {
121: private int val;
122:
123: public int getVal() {
124: return val;
125: }
126:
127: public void setVal(int val) {
128: this .val = val;
129: }
130:
131: public int getRealVal() {
132: return val;
133: }
134: }
135:
136: class FooKid extends Foo {
137: public int getDoubleVal() {
138: return getVal() * 2;
139: }
140: }
141:
142: class GetValAdapter extends ClassAdapter implements Opcodes,
143: ClassAdapterFactory {
144:
145: public GetValAdapter() {
146: super (null);
147: }
148:
149: public GetValAdapter(ClassVisitor cv) {
150: super (cv);
151: }
152:
153: public GetValAdapter(ClassVisitor visitor, ClassLoader loader) {
154: super (visitor);
155: }
156:
157: public MethodVisitor visitMethod(final int access,
158: final String name, final String desc,
159: final String signature, final String[] exceptions) {
160: if ("getVal".equals(name)) {
161: MethodVisitor mv = super .visitMethod(ACC_PUBLIC, "getVal",
162: "()I", null, null);
163: mv.visitCode();
164: mv.visitInsn(ICONST_M1);
165: mv.visitInsn(IRETURN);
166: mv.visitMaxs(0, 0);
167: mv.visitEnd();
168: return null;
169: }
170: return cv
171: .visitMethod(access, name, desc, signature, exceptions);
172: }
173:
174: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
175: return new GetValAdapter(visitor, loader);
176: }
177: }
|