1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.log4j.util;
19  
20  import junit.framework.TestCase;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.ByteArrayOutputStream;
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.FileOutputStream;
27  import java.io.IOException;
28  import java.io.ObjectInputStream;
29  import java.io.ObjectOutputStream;
30  
31  
32  /**
33   * Utiities for serialization tests.
34   *
35   * @author Curt Arnold
36   */
37  public class SerializationTestHelper {
38    /**
39     * Private constructor.
40     */
41    private SerializationTestHelper() {
42    }
43  
44    /**
45     * Creates a clone by serializing object and
46     * deserializing byte stream.
47     * @param obj object to serialize and deserialize.
48     * @return clone
49     * @throws IOException on IO error.
50     * @throws ClassNotFoundException if class not found.
51     */
52    public static Object serializeClone(final Object obj)
53      throws IOException, ClassNotFoundException {
54      ByteArrayOutputStream memOut = new ByteArrayOutputStream();
55      ObjectOutputStream objOut = new ObjectOutputStream(memOut);
56      objOut.writeObject(obj);
57      objOut.close();
58  
59      ByteArrayInputStream src = new ByteArrayInputStream(memOut.toByteArray());
60      ObjectInputStream objIs = new ObjectInputStream(src);
61  
62      return objIs.readObject();
63    }
64  
65    /**
66     * Deserializes a specified file.
67     * @param witness serialization file, may not be null.
68     * @return deserialized object.
69     * @throws Exception thrown on IO or deserialization exception.
70     */
71    public static Object deserializeStream(final String witness)
72      throws Exception {
73      FileInputStream fileIs = new FileInputStream(witness);
74      ObjectInputStream objIs = new ObjectInputStream(fileIs);
75  
76      return objIs.readObject();
77    }
78  
79    /**
80     * Checks the serialization of an object against an file
81     * containing the expected serialization.
82     *
83     * @param witness name of file containing expected serialization.
84     * @param obj object to be serialized.
85     * @param skip positions in serialized stream that should not be compared.
86     * @param endCompare position to stop comparison.
87     * @throws Exception thrown on IO or serialization exception.
88     */
89    public static void assertSerializationEquals(
90      final String witness, final Object obj, final int[] skip,
91      final int endCompare) throws Exception {
92      ByteArrayOutputStream memOut = new ByteArrayOutputStream();
93      ObjectOutputStream objOut = new ObjectOutputStream(memOut);
94      objOut.writeObject(obj);
95      objOut.close();
96  
97      assertStreamEquals(witness, memOut.toByteArray(), skip, endCompare);
98    }
99  
100   /**
101    * Asserts the serialized form of an object.
102    * @param witness file name of expected serialization.
103    * @param actual byte array of actual serialization.
104    * @param skip positions to skip comparison.
105    * @param endCompare position to stop comparison.
106    * @throws IOException thrown on IO or serialization exception.
107    */
108   public static void assertStreamEquals(
109     final String witness, final byte[] actual, final int[] skip,
110     final int endCompare) throws IOException {
111     File witnessFile = new File(witness);
112 
113     if (witnessFile.exists()) {
114       int skipIndex = 0;
115       byte[] expected = new byte[actual.length];
116       FileInputStream is = new FileInputStream(witnessFile);
117       int bytesRead = is.read(expected);
118       is.close();
119 
120       if(bytesRead < endCompare) {
121           TestCase.assertEquals(bytesRead, actual.length);
122       }
123 
124       int endScan = actual.length;
125 
126       if (endScan > endCompare) {
127         endScan = endCompare;
128       }
129 
130       for (int i = 0; i < endScan; i++) {
131         if ((skipIndex < skip.length) && (skip[skipIndex] == i)) {
132           skipIndex++;
133         } else {
134           if (expected[i] != actual[i]) {
135             TestCase.assertEquals(
136               "Difference at offset " + i, expected[i], actual[i]);
137           }
138         }
139       }
140     } else {
141       //
142       //  if the file doesn't exist then
143       //      assume that we are setting up and need to write it
144       FileOutputStream os = new FileOutputStream(witnessFile);
145       os.write(actual);
146       os.close();
147       TestCase.fail("Writing witness file " + witness);
148     }
149   }
150 }