1 /* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libcore.libcore.util; 18 19 import java.io.ByteArrayInputStream; 20 import java.io.ByteArrayOutputStream; 21 import java.io.IOException; 22 import java.io.ObjectInputStream; 23 import java.io.ObjectOutputStream; 24 import static junit.framework.Assert.assertEquals; 25 import static junit.framework.Assert.assertTrue; 26 import static junit.framework.Assert.fail; 27 import junit.framework.AssertionFailedError; 28 29 import libcore.util.HexEncoding; 30 31 public class SerializationTester<T> { 32 private final String golden; 33 private final T value; 34 SerializationTester(T value, String golden)35 public SerializationTester(T value, String golden) { 36 this.golden = golden; 37 this.value = value; 38 } 39 40 /** 41 * Returns true if {@code a} and {@code b} are equal. Override this if 42 * {@link Object#equals} isn't appropriate or sufficient for this tester's 43 * value type. 44 */ equals(T a, T b)45 protected boolean equals(T a, T b) { 46 return a.equals(b); 47 } 48 49 /** 50 * Verifies that {@code deserialized} is valid. Implementations of this 51 * method may mutate {@code deserialized}. 52 */ verify(T deserialized)53 protected void verify(T deserialized) throws Exception {} 54 test()55 public void test() { 56 try { 57 if (golden == null || golden.length() == 0) { 58 fail("No golden value supplied! Consider using this: " 59 + HexEncoding.encodeToString(serialize(value))); 60 } 61 62 @SuppressWarnings("unchecked") // deserialize should return the proper type 63 T deserialized = (T) deserialize(HexEncoding.decode(golden)); 64 assertTrue("User-constructed value doesn't equal deserialized golden value", 65 equals(value, deserialized)); 66 67 @SuppressWarnings("unchecked") // deserialize should return the proper type 68 T reserialized = (T) deserialize(serialize(value)); 69 assertTrue("User-constructed value doesn't equal itself, reserialized", 70 equals(value, reserialized)); 71 72 // just a confidence check! if this fails, verify() is probably broken 73 verify(value); 74 verify(deserialized); 75 verify(reserialized); 76 77 } catch (Exception e) { 78 Error failure = new AssertionFailedError(); 79 failure.initCause(e); 80 throw failure; 81 } 82 } 83 serialize(Object object)84 public static byte[] serialize(Object object) throws IOException { 85 ByteArrayOutputStream out = new ByteArrayOutputStream(); 86 new ObjectOutputStream(out).writeObject(object); 87 return out.toByteArray(); 88 } 89 deserialize(byte[] bytes)90 private static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException { 91 ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); 92 Object result = in.readObject(); 93 assertEquals(-1, in.read()); 94 return result; 95 } 96 97 /** 98 * Returns a serialized-and-deserialized copy of {@code object}. 99 */ reserialize(Object object)100 public static Object reserialize(Object object) throws IOException, ClassNotFoundException { 101 return deserialize(serialize(object)); 102 } 103 serializeHex(Object object)104 public static String serializeHex(Object object) throws IOException { 105 return HexEncoding.encodeToString(serialize(object)); 106 } 107 deserializeHex(String hex)108 public static Object deserializeHex(String hex) throws IOException, ClassNotFoundException { 109 return deserialize(HexEncoding.decode(hex)); 110 } 111 } 112