1 5 package com.tctest; 6 7 import org.apache.commons.io.IOUtils; 8 import org.apache.commons.lang.ClassUtils; 9 10 import com.tc.exception.TCNonPortableObjectError; 11 import com.tc.logging.CustomerLogging; 12 import com.tc.logging.LogLevel; 13 import com.tc.logging.TCAppender; 14 import com.tc.logging.TCLogging; 15 import com.tc.object.bytecode.Manageable; 16 import com.tc.object.config.ConfigVisitor; 17 import com.tc.object.config.DSOClientConfigHelper; 18 import com.tc.object.config.TransparencyClassSpec; 19 import com.tc.simulator.app.ApplicationConfig; 20 import com.tc.simulator.listener.ListenerProvider; 21 import com.tc.util.Assert; 22 import com.tctest.runner.AbstractErrorCatchingTransparentApp; 23 24 import java.io.ByteArrayOutputStream ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.net.ServerSocket ; 28 import java.util.ArrayList ; 29 import java.util.HashMap ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 import java.util.Map ; 33 34 public class NonPortableInstancesTest extends TransparentTestBase { 35 36 private static final int NODE_COUNT = 1; 37 38 public void doSetUp(TransparentTestIface t) throws Exception { 39 t.getTransparentAppConfig().setClientCount(NODE_COUNT); 40 t.initializeTestRunner(); 41 } 42 43 protected Class getApplicationClass() { 44 return App.class; 45 } 46 47 public static class App extends AbstractErrorCatchingTransparentApp { 48 49 private final Object [] array = new Object [1]; 50 private final Ref physicalObject = new Ref(); 51 private final List logicalObject = new ArrayList (); 52 private Object nonPortableRoot; 53 54 private final Map map = new HashMap (); 55 56 private final LogAppender logEvents; 57 58 public App(String appId, ApplicationConfig cfg, ListenerProvider listenerProvider) { 59 super(appId, cfg, listenerProvider); 60 61 logEvents = new LogAppender(); 62 63 TCLogging.addAppender(CustomerLogging.getDSORuntimeLogger().getName(), logEvents); 64 } 65 66 public Object getNonPortableRoot() { 67 return nonPortableRoot; 69 } 70 71 protected void runTest() throws Throwable { 72 73 try { 75 synchronized (array) { 76 array[0] = new NotPortable(); 77 } 78 throw new AssertionError (); 79 } catch (TCNonPortableObjectError e) { 80 } 82 validate(1); 83 84 try { 86 synchronized (physicalObject) { 87 physicalObject.setRef(new NotPortable()); 88 } 89 throw new AssertionError (); 90 } catch (TCNonPortableObjectError e) { 91 } 93 validate(1); 94 95 try { 97 synchronized (logicalObject) { 98 logicalObject.add(new NotPortable()); 99 } 100 throw new AssertionError (); 101 } catch (TCNonPortableObjectError e) { 102 } 104 validate(1); 105 106 try { 108 nonPortableRoot = new NotPortable(); 109 throw new AssertionError (); 110 } catch (TCNonPortableObjectError e) { 111 } 113 validate(1); 114 115 try { 118 synchronized (map) { 119 map.put("key", new Portable()); 120 } 121 throw new AssertionError (); 122 } catch (TCNonPortableObjectError e) { 123 } 125 validate(2); 126 127 } 128 129 private void validate(int i) throws IOException { 130 String expect = getExpected(i); 131 String actual = logEvents.takeLoggedMessages(); 132 133 expect = expect.replaceAll("\r", ""); 134 actual = actual.replaceAll("\r", ""); 135 136 Assert.assertEquals(expect, actual); 137 } 138 139 private String getExpected(int i) throws IOException { 140 String resource = ClassUtils.getShortClassName(getClass()) + "-dump" + i + ".txt"; 141 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 142 143 InputStream in = null; 144 try { 145 in = getClass().getResourceAsStream(resource); 146 if (in == null) { 147 fail("missing resource: " + resource); 148 } 149 IOUtils.copy(in, baos); 150 } finally { 151 if (in != null) { 152 try { 153 in.close(); 154 } catch (Exception e) { 155 throw new RuntimeException (e); 156 } 157 } 158 } 159 160 baos.flush(); 161 return new String (baos.toByteArray()); 162 } 163 164 public static void visitL1DSOConfig(ConfigVisitor visitor, DSOClientConfigHelper config) { 165 config.getOrCreateSpec(Ref.class.getName()); 166 TransparencyClassSpec spec = config.getOrCreateSpec(Portable.class.getName()); 167 spec.setHonorTransient(true); 168 spec.addTransient("ss"); 169 170 String testClass = App.class.getName(); 171 spec = config.getOrCreateSpec(testClass); 172 String methodExpr = "* " + testClass + "*.*(..)"; 173 config.addWriteAutolock(methodExpr); 174 175 spec.addRoot("logicalObject", "logicalObject"); 176 spec.addRoot("array", "array"); 177 spec.addRoot("physicalObject", "physicalObject"); 178 spec.addRoot("nonPortableRoot", "nonPortableRoot"); 179 180 spec.addRoot("map", "map"); 181 } 182 183 } 184 185 private static class Ref { 186 private Object ref; 187 188 Object getRef() { 189 return ref; 190 } 191 192 void setRef(Object ref) { 193 this.ref = ref; 194 } 195 196 } 197 198 private static class Portable { 199 Ref ref = new Ref(); 200 201 transient Runtime honeredTransient = Runtime.getRuntime(); 202 ServerSocket ss; 204 Portable() { 205 ref.setRef(makeGraphWithNonPortableNodes(new NotPortable())); 206 try { 207 ss = new ServerSocket (); 208 } catch (IOException e) { 209 throw new AssertionError (e); 210 } 211 } 212 } 213 214 private static class NotPortable { 215 final Map m = makeGraphWithNonPortableNodes(this); 216 217 Thread t = Thread.currentThread(); 218 219 NotPortable() { 220 if (this instanceof Manageable) { throw new AssertionError ("this type should not be portable"); } 221 } 222 } 223 224 private static Map makeGraphWithNonPortableNodes(Object nonPortable) { 225 Map m = new HashMap (); 226 Ref ref = new Ref(); 227 Ref r2 = new Ref(); 228 r2.setRef(nonPortable); 229 ref.setRef(r2); 230 231 m.put("ref", ref); 232 233 Object [][] a = new Object [][] { { null }, { new Ref() } }; 234 ((Ref) a[1][0]).setRef(m); 235 236 return m; 237 } 238 239 private static class LogAppender implements TCAppender { 240 241 private final List events = new ArrayList (); 242 243 public void append(LogLevel level, Object message, Throwable throwable) { 244 events.add(new Event(level, message, throwable)); 245 } 246 247 String takeLoggedMessages() { 248 StringBuffer buf = new StringBuffer (); 249 for (Iterator iter = events.iterator(); iter.hasNext();) { 250 Event event = (Event) iter.next(); 251 buf.append(event.getMessage() + "\n"); 252 } 253 254 events.clear(); 255 256 return buf.toString(); 257 } 258 259 } 260 261 static class Event { 262 private final LogLevel level; 263 private final Object message; 264 private final Throwable throwable; 265 266 Event(LogLevel level, Object message, Throwable throwable) { 267 this.level = level; 268 this.message = message; 269 this.throwable = throwable; 270 } 271 272 public LogLevel getLevel() { 273 return level; 274 } 275 276 public Object getMessage() { 277 return message; 278 } 279 280 public Throwable getThrowable() { 281 return throwable; 282 } 283 284 public String toString() { 285 return "[" + level + "] " + message + ((throwable == null) ? "" : throwable.getMessage()); 286 } 287 } 288 289 } 290 | Popular Tags |