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