SerializationTester.java revision 8033ba2bd4b8eab11e67738ba4d1390e1fb72111
1984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson/* 2984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Copyright (C) 2010 Google Inc. 3984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 4984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * you may not use this file except in compliance with the License. 6984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * You may obtain a copy of the License at 7984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 8984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 10984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Unless required by applicable law or agreed to in writing, software 11984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * See the License for the specific language governing permissions and 14984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * limitations under the License. 15984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 16984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 174557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonpackage libcore.java.util; 18984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 19984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport java.io.ByteArrayInputStream; 20984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport java.io.ByteArrayOutputStream; 21984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport java.io.IOException; 22984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport java.io.ObjectInputStream; 23984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport java.io.ObjectOutputStream; 248033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilsonimport static junit.framework.Assert.*; 25984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport junit.framework.AssertionFailedError; 26984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 27984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonpublic class SerializableTester<T> { 28984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 29984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private final String golden; 30984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private final T value; 31984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 32984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SerializableTester(T value, String golden) { 33984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.golden = golden; 34984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.value = value; 35984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 36984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 3719a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson /** 3819a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson * Returns true if {@code a} and {@code b} are equal. Override this if 3919a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson * {@link Object#equals} isn't appropriate or sufficient for this tester's 4019a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson * value type. 4119a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson */ 4219a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson protected boolean equals(T a, T b) { 4319a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson return a.equals(b); 4419a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson } 4519a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson 468033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilson /** 478033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilson * Verifies that {@code deserialized} is valid. Implementations of this 488033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilson * method may mutate {@code deserialized}. 498033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilson */ 50984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson protected void verify(T deserialized) {} 51984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 52984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public void test() { 53984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson try { 54984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (golden == null || golden.length() == 0) { 55984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson fail("No golden value supplied! Consider using this: " 56984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson + hexEncode(serialize(value))); 57984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 58984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 59984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // deserialize should return the proper type 60984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson T deserialized = (T) deserialize(hexDecode(golden)); 6119a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson assertTrue("User-constructed value doesn't equal deserialized golden value", 6219a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson equals(value, deserialized)); 63984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 64984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // deserialize should return the proper type 65984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson T reserialized = (T) deserialize(serialize(value)); 6619a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson assertTrue("User-constructed value doesn't equal itself, reserialized", 6719a270e90b1e992c1f6639f355ae13564c2f3a6aJesse Wilson equals(value, reserialized)); 688033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilson 698033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilson // just a sanity check! if this fails, verify() is probably broken 708033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilson verify(value); 718033ba2bd4b8eab11e67738ba4d1390e1fb72111Jesse Wilson verify(deserialized); 72984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson verify(reserialized); 73984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 74984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } catch (Exception e) { 75984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Error failure = new AssertionFailedError(); 76984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson failure.initCause(e); 77984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw failure; 78984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 79984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 80984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 81984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private byte[] serialize(Object object) throws IOException { 82984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson ByteArrayOutputStream out = new ByteArrayOutputStream(); 83984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson new ObjectOutputStream(out).writeObject(object); 84984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return out.toByteArray(); 85984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 86984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 87984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException { 88984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); 89984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Object result = in.readObject(); 90984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson assertEquals(-1, in.read()); 91984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result; 92984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 93984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 94984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private String hexEncode(byte[] bytes) { 95984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson StringBuilder result = new StringBuilder(bytes.length * 2); 96984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson for (byte b : bytes) { 97984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson result.append(String.format("%02x", b)); 98984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 99984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result.toString(); 100984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 101984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 102984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private byte[] hexDecode(String s) { 103984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson byte[] result = new byte[s.length() / 2]; 104984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson for (int i = 0; i < result.length; i++) { 105984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson result[i] = (byte) Integer.parseInt(s.substring(i*2, i*2 + 2), 16); 106984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 107984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result; 108984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 109984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson} 110984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 111