1 4 package com.tc.objectserver.managedobject; 5 6 import com.tc.exception.ImplementMe; 7 import com.tc.io.serializer.TCObjectInputStream; 8 import com.tc.io.serializer.TCObjectOutputStream; 9 import com.tc.object.ObjectID; 10 import com.tc.object.SerializationUtil; 11 import com.tc.object.dna.api.DNACursor; 12 import com.tc.object.dna.api.DNAWriter; 13 import com.tc.object.dna.api.LiteralAction; 14 import com.tc.object.dna.api.LogicalAction; 15 import com.tc.object.dna.api.PhysicalAction; 16 import com.tc.object.dna.impl.DNAEncoding; 17 import com.tc.objectserver.core.api.ManagedObjectState; 18 import com.tc.objectserver.persistence.impl.InMemoryPersistor; 19 import com.tc.util.Assert; 20 21 import java.io.ByteArrayInputStream ; 22 import java.io.ByteArrayOutputStream ; 23 import java.lang.reflect.Field ; 24 import java.lang.reflect.InvocationHandler ; 25 import java.lang.reflect.Method ; 26 import java.lang.reflect.Modifier ; 27 import java.lang.reflect.Proxy ; 28 import java.util.ArrayList ; 29 import java.util.Arrays ; 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 35 import junit.framework.TestCase; 36 37 public class ManagedObjectStateSerializationTest extends TestCase { 38 private static final String loaderDesc = "System.loader"; 39 40 private ObjectID objectID; 41 private ManagedObjectChangeListenerProvider listenerProvider; 42 43 public void setUp() throws Exception { 44 super.setUp(); 45 listenerProvider = new NullManagedObjectChangeListenerProvider(); 46 ManagedObjectStateFactory.disableSingleton(true); 47 ManagedObjectStateFactory.createInstance(listenerProvider, new InMemoryPersistor()); 48 objectID = new ObjectID(2000); 49 } 50 51 protected void tearDown() throws Exception { 52 super.tearDown(); 53 ManagedObjectStateFactory.disableSingleton(false); 54 objectID = null; 55 listenerProvider = null; 56 } 57 58 public void testCheckIfMissingAnyManagedObjectType() throws Exception { 59 Field [] fields = ManagedObjectState.class.getDeclaredFields(); 60 61 for (int i = 0; i < fields.length; i++) { 62 Field field = fields[i]; 63 64 int fieldModifier = field.getModifiers(); 65 if (Modifier.isStatic(fieldModifier) && Modifier.isFinal(fieldModifier)) { 66 Byte type = (Byte ) field.get(null); 67 switch (type.byteValue()) { 68 case ManagedObjectState.PHYSICAL_TYPE: 69 testPhysical(); 70 break; 71 case ManagedObjectState.DATE_TYPE: 72 testDate(); 73 break; 74 case ManagedObjectState.MAP_TYPE: 75 case ManagedObjectState.PARTIAL_MAP_TYPE: 76 break; 78 case ManagedObjectState.LINKED_HASHMAP_TYPE: 79 testLinkedHashMap(); 80 break; 81 case ManagedObjectState.ARRAY_TYPE: 82 testArray(); 83 break; 84 case ManagedObjectState.LITERAL_TYPE: 85 testLiteral(); 86 break; 87 case ManagedObjectState.LIST_TYPE: 88 testList(); 89 break; 90 case ManagedObjectState.SET_TYPE: 91 testSet(); 92 break; 93 case ManagedObjectState.TREE_SET_TYPE: 94 testTreeSet(); 95 break; 96 case ManagedObjectState.TREE_MAP_TYPE: 97 testTreeMap(); 98 break; 99 case ManagedObjectState.QUEUE_TYPE: 100 testLinkedBlockingQueue(); 101 break; 102 case ManagedObjectState.CONCURRENT_HASHMAP_TYPE: 103 testConcurrentHashMap(); 104 break; 105 case ManagedObjectState.PROXY_TYPE: 106 testProxy(); 107 break; 108 default: 109 throw new AssertionError ("Type " + type 110 + " does not have a test case in ManagedObjectStateSerializationTest."); 111 } 112 } 113 } 114 } 115 116 public void testProxy() throws Exception { 117 String CLASSLOADER_FIELD_NAME = "java.lang.reflect.Proxy.loader"; 118 String INTERFACES_FIELD_NAME = "java.lang.reflect.Proxy.interfaces"; 119 String INVOCATION_HANDLER_FIELD_NAME = "java.lang.reflect.Proxy.h"; 120 121 MyInvocationHandler handler = new MyInvocationHandler(); 122 Proxy myProxy = (Proxy ) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class [] { MyProxyInf1.class, 123 MyProxyInf2.class }, handler); 124 String className = myProxy.getClass().getName(); 125 126 TestDNACursor cursor = new TestDNACursor(); 127 128 cursor.addPhysicalAction(CLASSLOADER_FIELD_NAME, myProxy.getClass().getClassLoader(), true); 129 cursor.addPhysicalAction(INTERFACES_FIELD_NAME, myProxy.getClass().getInterfaces(), true); 130 cursor.addPhysicalAction(INVOCATION_HANDLER_FIELD_NAME, new ObjectID(2002), true); 131 132 ManagedObjectState state = applyValidation(className, cursor); 133 134 serializationValidation(state, cursor, ManagedObjectState.PHYSICAL_TYPE); 135 } 136 137 public void testPhysical() throws Exception { 138 String className = "com.tc.objectserver.managedobject.ManagedObjectStateSerializationTest"; 139 TestDNACursor cursor = new TestDNACursor(); 140 141 cursor.addPhysicalAction("field1", new ObjectID(2002), true); 142 cursor.addPhysicalAction("field2", new ObjectID(2003), true); 143 cursor.addPhysicalAction("field3", new Integer (33), false); 144 145 ManagedObjectState state = applyValidation(className, cursor); 146 147 serializationValidation(state, cursor, ManagedObjectState.PHYSICAL_TYPE); 148 } 149 150 public void testDate() throws Exception { 151 String className = "java.util.Date"; 152 153 TestDNACursor cursor = new TestDNACursor(); 154 155 cursor.addLogicalAction(SerializationUtil.SET_TIME, new Long [] { new Long (System.currentTimeMillis()) }); 156 cursor.addLogicalAction(SerializationUtil.SET_NANOS, new Integer [] { new Integer (0) }); 157 158 ManagedObjectState state = applyValidation(className, cursor); 159 160 serializationValidation(state, cursor, ManagedObjectState.DATE_TYPE); 161 } 162 163 public void testLinkedHashMap() throws Exception { 164 String className = "java.util.LinkedHashMap"; 165 String ACCESS_ORDER_FIELDNAME = "java.util.LinkedHashMap.accessOrder"; 166 167 TestDNACursor cursor = new TestDNACursor(); 168 169 cursor.addPhysicalAction(ACCESS_ORDER_FIELDNAME, Boolean.FALSE, false); 170 171 cursor.addLogicalAction(SerializationUtil.PUT, new Object [] { new ObjectID(2002), new ObjectID(2003) }); 172 cursor.addLogicalAction(SerializationUtil.PUT, new Object [] { new ObjectID(2004), new ObjectID(2005) }); 173 174 ManagedObjectState state = applyValidation(className, cursor); 175 176 serializationValidation(state, cursor, ManagedObjectState.LINKED_HASHMAP_TYPE); 177 } 178 179 public void testArray() throws Exception { 180 String className = "[java.lang.Integer"; 181 TestDNACursor cursor = new TestDNACursor(); 182 183 cursor.addArrayAction(new Integer [] { new Integer (27) }); 184 185 ManagedObjectState state = applyValidation(className, cursor); 186 187 serializationValidation(state, cursor, ManagedObjectState.ARRAY_TYPE); 188 } 189 190 public void testLiteral() throws Exception { 191 String className = "java.lang.Integer"; 192 TestDNACursor cursor = new TestDNACursor(); 193 194 cursor.addLiteralAction(new Integer (27)); 195 196 ManagedObjectState state = applyValidation(className, cursor); 197 198 serializationValidation(state, cursor, ManagedObjectState.LITERAL_TYPE); 199 } 200 201 public void testList() throws Exception { 202 String className = "java.util.ArrayList"; 203 TestDNACursor cursor = new TestDNACursor(); 204 205 cursor.addLogicalAction(SerializationUtil.ADD, new Object [] { new ObjectID(2002) }); 206 cursor.addLogicalAction(SerializationUtil.ADD, new Object [] { new ObjectID(2003) }); 207 208 ManagedObjectState state = applyValidation(className, cursor); 209 210 serializationValidation(state, cursor, ManagedObjectState.LIST_TYPE); 211 } 212 213 public void testSet() throws Exception { 214 String className = "java.util.HashSet"; 215 TestDNACursor cursor = new TestDNACursor(); 216 217 cursor.addLogicalAction(SerializationUtil.ADD, new Object [] { new ObjectID(2002) }); 218 cursor.addLogicalAction(SerializationUtil.ADD, new Object [] { new ObjectID(2003) }); 219 220 ManagedObjectState state = applyValidation(className, cursor); 221 222 serializationValidation(state, cursor, ManagedObjectState.SET_TYPE); 223 } 224 225 public void testTreeSet() throws Exception { 226 String className = "java.util.TreeSet"; 227 String COMPARATOR_FIELDNAME = "java.util.TreeMap.comparator"; 228 229 TestDNACursor cursor = new TestDNACursor(); 230 231 cursor.addPhysicalAction(COMPARATOR_FIELDNAME, new ObjectID(2001), true); 232 233 cursor.addLogicalAction(SerializationUtil.ADD, new Object [] { new ObjectID(2002) }); 234 cursor.addLogicalAction(SerializationUtil.ADD, new Object [] { new ObjectID(2003) }); 235 236 ManagedObjectState state = applyValidation(className, cursor); 237 238 serializationValidation(state, cursor, ManagedObjectState.TREE_SET_TYPE); 239 } 240 241 public void testTreeMap() throws Exception { 242 String className = "java.util.TreeMap"; 243 String COMPARATOR_FIELDNAME = "java.util.TreeMap.comparator"; 244 245 TestDNACursor cursor = new TestDNACursor(); 246 247 cursor.addPhysicalAction(COMPARATOR_FIELDNAME, new ObjectID(2001), true); 248 249 cursor.addLogicalAction(SerializationUtil.PUT, new Object [] { new ObjectID(2002), new ObjectID(2003) }); 250 cursor.addLogicalAction(SerializationUtil.PUT, new Object [] { new ObjectID(2004), new ObjectID(2005) }); 251 252 ManagedObjectState state = applyValidation(className, cursor); 253 254 serializationValidation(state, cursor, ManagedObjectState.TREE_MAP_TYPE); 255 } 256 257 public void testLinkedBlockingQueue() throws Exception { 258 String className = "java.util.concurrent.LinkedBlockingQueue"; 259 String TAKE_LOCK_FIELD_NAME = "java.util.concurrent.LinkedBlockingQueue.takeLock"; 260 String PUT_LOCK_FIELD_NAME = "java.util.concurrent.LinkedBlockingQueue.putLock"; 261 String CAPACITY_FIELD_NAME = "java.util.concurrent.LinkedBlockingQueue.capacity"; 262 263 TestDNACursor cursor = new TestDNACursor(); 264 265 cursor.addPhysicalAction(TAKE_LOCK_FIELD_NAME, new ObjectID(2001), true); 266 cursor.addPhysicalAction(PUT_LOCK_FIELD_NAME, new ObjectID(2002), true); 267 cursor.addPhysicalAction(CAPACITY_FIELD_NAME, new Integer (100), false); 268 269 cursor.addLogicalAction(SerializationUtil.PUT, new Object [] { new ObjectID(2003) }); 270 cursor.addLogicalAction(SerializationUtil.PUT, new Object [] { new ObjectID(2004) }); 271 272 ManagedObjectState state = applyValidation(className, cursor); 273 274 serializationValidation(state, cursor, ManagedObjectState.QUEUE_TYPE); 275 } 276 277 public void testConcurrentHashMap() throws Exception { 278 String className = "java.util.concurrent.ConcurrentHashMap"; 279 String SEGMENT_MASK_FIELD_NAME = className + ".segmentMask"; 280 String SEGMENT_SHIFT_FIELD_NAME = className + ".segmentShift"; 281 String SEGMENT_FIELD_NAME = className + ".segments"; 282 283 TestDNACursor cursor = new TestDNACursor(); 284 285 cursor.addPhysicalAction(SEGMENT_MASK_FIELD_NAME, new Integer (10), false); 286 cursor.addPhysicalAction(SEGMENT_SHIFT_FIELD_NAME, new Integer (20), false); 287 cursor.addLiteralAction(new Integer (2)); 288 cursor.addPhysicalAction(SEGMENT_FIELD_NAME+0, new ObjectID(2001), true); 289 cursor.addPhysicalAction(SEGMENT_FIELD_NAME+1, new ObjectID(2002), true); 290 291 cursor.addLogicalAction(SerializationUtil.PUT, new Object [] { new ObjectID(2002), new ObjectID(2003) }); 292 cursor.addLogicalAction(SerializationUtil.PUT, new Object [] { new ObjectID(2004), new ObjectID(2005) }); 293 294 ManagedObjectState state = applyValidation(className, cursor); 295 296 serializationValidation(state, cursor, ManagedObjectState.CONCURRENT_HASHMAP_TYPE); 297 } 298 299 private ManagedObjectState applyValidation(String className, DNACursor dnaCursor) throws Exception { 300 ManagedObjectState state = apply(className, dnaCursor); 301 TestDNAWriter dnaWriter = dehydrate(state); 302 validate(dnaCursor, dnaWriter); 303 304 return state; 305 } 306 307 private void serializationValidation(ManagedObjectState state, DNACursor dnaCursor, byte type) throws Exception { 308 byte[] buffer = writeTo(state); 309 TestDNAWriter dnaWriter = readFrom(type, buffer); 310 validate(dnaCursor, dnaWriter); 311 } 312 313 private byte[] writeTo(ManagedObjectState state) throws Exception { 314 ByteArrayOutputStream bout = new ByteArrayOutputStream (); 315 TCObjectOutputStream out = new TCObjectOutputStream(bout); 316 state.writeTo(out); 317 318 return bout.toByteArray(); 319 } 320 321 private TestDNAWriter readFrom(byte type, byte[] buffer) throws Exception { 322 ByteArrayInputStream bin = new ByteArrayInputStream (buffer); 323 TCObjectInputStream in = new TCObjectInputStream(bin); 324 325 ManagedObjectState state = ManagedObjectStateFactory.getInstance().readManagedObjectStateFrom(in, type); 326 return dehydrate(state); 327 } 328 329 private ManagedObjectState apply(String className, DNACursor dnaCursor) throws Exception { 330 ManagedObjectState state = ManagedObjectStateFactory.getInstance().createState(new ObjectID(1), ObjectID.NULL_ID, 331 className, loaderDesc, dnaCursor); 332 state.apply(objectID, dnaCursor, new BackReferences()); 333 return state; 334 } 335 336 private TestDNAWriter dehydrate(ManagedObjectState state) throws Exception { 337 TestDNAWriter dnaWriter = new TestDNAWriter(); 338 state.dehydrate(objectID, dnaWriter); 339 return dnaWriter; 340 } 341 342 private void validate(DNACursor dnaCursor, TestDNAWriter writer) throws Exception { 343 Assert.assertEquals(dnaCursor.getActionCount(), writer.getActionCount()); 344 dnaCursor.reset(); 345 while (dnaCursor.next()) { 346 Object action = dnaCursor.getAction(); 347 Assert.assertTrue(writer.containsAction(action)); 348 } 349 } 350 351 public class TestDNAWriter implements DNAWriter { 352 private List physicalActions = new ArrayList (); 353 private List logicalActions = new ArrayList (); 354 private List literalActions = new ArrayList (); 355 356 public TestDNAWriter() { 357 } 359 360 public void addLogicalAction(int method, Object [] parameters) { 361 logicalActions.add(new LogicalAction(method, parameters)); 362 } 363 364 public void addPhysicalAction(String field, Object value) { 365 addPhysicalAction(field, value, value instanceof ObjectID); 366 } 367 368 public void finalizeDNA() { 369 } 371 372 public void addArrayElementAction(int index, Object value) { 373 } 375 376 public void addEntireArray(Object value) { 377 physicalActions.add(new PhysicalAction(value)); 378 } 379 380 public void addLiteralValue(Object value) { 381 literalActions.add(new LiteralAction(value)); 382 } 383 384 public void setParentObjectID(ObjectID id) { 385 } 387 388 public void setArrayLength(int length) { 389 } 391 392 public void addPhysicalAction(String fieldName, Object value, boolean canBeReference) { 393 physicalActions.add(new PhysicalAction(fieldName, value, canBeReference)); 394 } 395 396 public int getActionCount() { 397 return logicalActions.size() + physicalActions.size() + literalActions.size(); 398 } 399 400 private boolean containsAction(Object targetAction) { 401 if (targetAction instanceof LogicalAction) { 402 return containsLogicalAction((LogicalAction) targetAction); 403 } else if (targetAction instanceof PhysicalAction) { 404 return containsPhysicalAction((PhysicalAction) targetAction); 405 } else if (targetAction instanceof LiteralAction) { return containsLiteralAction((LiteralAction) targetAction); } 406 407 return false; 408 } 409 410 private boolean containsLogicalAction(LogicalAction targetAction) { 411 for (Iterator i = logicalActions.iterator(); i.hasNext();) { 412 LogicalAction action = (LogicalAction) i.next(); 413 if (identicalLogicalAction(targetAction, action)) { return true; } 414 } 415 return false; 416 } 417 418 private boolean containsPhysicalAction(PhysicalAction targetAction) { 419 for (Iterator i = physicalActions.iterator(); i.hasNext();) { 420 PhysicalAction action = (PhysicalAction) i.next(); 421 if (identicalPhysicalAction(targetAction, action)) { return true; } 422 } 423 return false; 424 } 425 426 private boolean containsLiteralAction(LiteralAction targetAction) { 427 for (Iterator i = literalActions.iterator(); i.hasNext();) { 428 LiteralAction action = (LiteralAction) i.next(); 429 if (identicalLiteralAction(targetAction, action)) { return true; } 430 } 431 return false; 432 } 433 434 private boolean identicalLiteralAction(LiteralAction a1, LiteralAction a2) { 435 if (a1 == null || a2 == null) { return false; } 436 if (a1.getObject() == null || a2.getObject() == null) { return false; } 437 438 return a1.getObject().equals(a2.getObject()); 439 } 440 441 private boolean identicalPhysicalAction(PhysicalAction a1, PhysicalAction a2) { 442 if (a1 == null || a2 == null) { return false; } 443 444 if (!a1.isEntireArray() && !a2.isEntireArray()) { 445 if (a1.getFieldName() == null || a2.getFieldName() == null) { return false; } 446 } 447 448 if (a1.isEntireArray() != a2.isEntireArray()) { return false; } 449 450 if (a1.getObject() == null && a2.getObject() == null) { return true; } 451 if (a1.getObject() == null && a2.getObject() != null) { return false; } 452 if (a1.getObject() != null && a2.getObject() == null) { return false; } 453 454 if (a1.isEntireArray()) { 455 return Arrays.equals((Object []) a1.getObject(), (Object []) a2.getObject()); 456 } else if (a1.getObject() instanceof Object [] && a2.getObject() instanceof Object []) { 457 return Arrays.equals((Object []) a1.getObject(), (Object []) a2.getObject()); 458 } else { 459 if (a1.getFieldName().equals(a2.getFieldName())) { return (a1.getObject().equals(a2.getObject())); } 460 } 461 return false; 462 } 463 464 private boolean identicalLogicalAction(LogicalAction a1, LogicalAction a2) { 465 if (a1 == null || a2 == null) { return false; } 466 if (a1.getParameters() == null || a2.getParameters() == null) { return false; } 467 468 if (a1.getMethod() == a2.getMethod()) { 469 if (a1.getParameters().length == a2.getParameters().length) { 470 for (int i = 0; i < a1.getParameters().length; i++) { 471 if (!a1.getParameters()[i].equals(a2.getParameters()[i])) { return false; } 472 } 473 return true; 474 } 475 } 476 return false; 477 } 478 479 public void addClassLoaderAction(String classLoaderFieldName, Object value) { 480 482 } 483 484 public void addSubArrayAction(int start, Object array, int length) { 485 } 487 } 488 489 public class TestDNACursor implements DNACursor { 490 private List actions = new ArrayList (); 491 private int current = -1; 492 493 public void addPhysicalAction(String addFieldName, Object addObj, boolean isref) { 494 actions.add(new PhysicalAction(addFieldName, addObj, isref)); 495 } 496 497 public void addLogicalAction(int method, Object params[]) { 498 actions.add(new LogicalAction(method, params)); 499 } 500 501 public void addArrayAction(Object [] objects) { 502 actions.add(new PhysicalAction(objects)); 503 } 504 505 public void addLiteralAction(Object value) { 506 actions.add(new LiteralAction(value)); 507 } 508 509 public boolean next() { 510 return actions.size() > ++current; 511 } 512 513 public LogicalAction getLogicalAction() { 514 return (LogicalAction) actions.get(current); 515 } 516 517 public Object getAction() { 518 return actions.get(current); 519 } 520 521 public PhysicalAction getPhysicalAction() { 522 return (PhysicalAction) actions.get(current); 523 } 524 525 public boolean next(DNAEncoding encoding) { 526 throw new ImplementMe(); 527 } 528 529 public int getActionCount() { 530 return actions.size(); 531 } 532 533 public void reset() throws UnsupportedOperationException { 534 current = -1; 535 } 536 } 537 538 public interface MyProxyInf1 { 539 public int getValue(); 540 541 public void setValue(int i); 542 } 543 544 public interface MyProxyInf2 { 545 public String getStringValue(); 546 547 public void setStringValue(String str); 548 } 549 550 public static class MyInvocationHandler implements InvocationHandler { 551 private Map values = new HashMap (); 552 private Map stringValues = new HashMap (); 553 554 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 555 if (method.getName().equals("getValue")) { 556 return values.get(proxy); 557 } else if (method.getName().equals("setValue")) { 558 values.put(proxy, args[0]); 559 return null; 560 } else if (method.getName().equals("setStringValue")) { 561 stringValues.put(proxy, args[0]); 562 return null; 563 } else if (method.getName().equals("getStringValue")) { 564 return stringValues.get(proxy); 565 } else if (method.getName().equals("hashCode")) { return new Integer (System.identityHashCode(proxy)); } 566 return null; 567 } 568 } 569 } 570 | Popular Tags |