• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package org.apache.commons.lang3;
18 
19 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertNotNull;
23 import static org.junit.jupiter.api.Assertions.assertNotSame;
24 import static org.junit.jupiter.api.Assertions.assertNull;
25 import static org.junit.jupiter.api.Assertions.assertSame;
26 import static org.junit.jupiter.api.Assertions.assertThrows;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 
29 import java.io.ByteArrayInputStream;
30 import java.io.ByteArrayOutputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.ObjectInputStream;
34 import java.io.ObjectOutputStream;
35 import java.io.OutputStream;
36 import java.io.Serializable;
37 import java.lang.reflect.Constructor;
38 import java.lang.reflect.Modifier;
39 import java.util.HashMap;
40 
41 import org.junit.jupiter.api.BeforeEach;
42 import org.junit.jupiter.api.Test;
43 
44 /**
45  * Unit tests {@link org.apache.commons.lang3.SerializationUtils}.
46  */
47 public class SerializationUtilsTest extends AbstractLangTest {
48 
49   static final String CLASS_NOT_FOUND_MESSAGE = "ClassNotFoundSerialization.readObject fake exception";
50     protected static final String SERIALIZE_IO_EXCEPTION_MESSAGE = "Anonymous OutputStream I/O exception";
51 
52     private String iString;
53     private Integer iInteger;
54     private HashMap<Object, Object> iMap;
55 
56     @BeforeEach
setUp()57     public void setUp() {
58         iString = "foo";
59         iInteger = Integer.valueOf(7);
60         iMap = new HashMap<>();
61         iMap.put("FOO", iString);
62         iMap.put("BAR", iInteger);
63     }
64 
65 
66     @Test
testConstructor()67     public void testConstructor() {
68         assertNotNull(new SerializationUtils());
69         final Constructor<?>[] cons = SerializationUtils.class.getDeclaredConstructors();
70         assertEquals(1, cons.length);
71         assertTrue(Modifier.isPublic(cons[0].getModifiers()));
72         assertTrue(Modifier.isPublic(SerializationUtils.class.getModifiers()));
73         assertFalse(Modifier.isFinal(SerializationUtils.class.getModifiers()));
74     }
75 
76     @Test
testException()77     public void testException() {
78         SerializationException serEx;
79         final Exception ex = new Exception();
80 
81         serEx = new SerializationException();
82         assertSame(null, serEx.getMessage());
83         assertSame(null, serEx.getCause());
84 
85         serEx = new SerializationException("Message");
86         assertSame("Message", serEx.getMessage());
87         assertSame(null, serEx.getCause());
88 
89         serEx = new SerializationException(ex);
90         assertEquals("java.lang.Exception", serEx.getMessage());
91         assertSame(ex, serEx.getCause());
92 
93         serEx = new SerializationException("Message", ex);
94         assertSame("Message", serEx.getMessage());
95         assertSame(ex, serEx.getCause());
96     }
97 
98 
99     @Test
testSerializeStream()100     public void testSerializeStream() throws Exception {
101         final ByteArrayOutputStream streamTest = new ByteArrayOutputStream();
102         SerializationUtils.serialize(iMap, streamTest);
103 
104         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
105         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
106             oos.writeObject(iMap);
107             oos.flush();
108         }
109 
110         final byte[] testBytes = streamTest.toByteArray();
111         final byte[] realBytes = streamReal.toByteArray();
112         assertEquals(testBytes.length, realBytes.length);
113         assertArrayEquals(realBytes, testBytes);
114     }
115 
116     @Test
testSerializeStreamUnserializable()117     public void testSerializeStreamUnserializable() {
118         final ByteArrayOutputStream streamTest = new ByteArrayOutputStream();
119         iMap.put(new Object(), new Object());
120         assertThrows(SerializationException.class, () -> SerializationUtils.serialize(iMap, streamTest));
121     }
122 
123     @Test
testSerializeStreamNullObj()124     public void testSerializeStreamNullObj() throws Exception {
125         final ByteArrayOutputStream streamTest = new ByteArrayOutputStream();
126         SerializationUtils.serialize(null, streamTest);
127 
128         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
129         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
130             oos.writeObject(null);
131             oos.flush();
132         }
133 
134         final byte[] testBytes = streamTest.toByteArray();
135         final byte[] realBytes = streamReal.toByteArray();
136         assertEquals(testBytes.length, realBytes.length);
137         assertArrayEquals(realBytes, testBytes);
138     }
139 
140     @Test
testSerializeStreamObjNull()141     public void testSerializeStreamObjNull() {
142         assertThrows(NullPointerException.class, () -> SerializationUtils.serialize(iMap, null));
143     }
144 
145     @Test
testSerializeStreamNullNull()146     public void testSerializeStreamNullNull() {
147         assertThrows(NullPointerException.class, () -> SerializationUtils.serialize(null, null));
148     }
149 
150     @Test
testSerializeIOException()151     public void testSerializeIOException() {
152         // forces an IOException when the ObjectOutputStream is created, to test not closing the stream
153         // in the finally block
154         final OutputStream streamTest = new OutputStream() {
155             @Override
156             public void write(final int arg0) throws IOException {
157                 throw new IOException(SERIALIZE_IO_EXCEPTION_MESSAGE);
158             }
159         };
160         final SerializationException e =
161                 assertThrows(SerializationException.class, () -> SerializationUtils.serialize(iMap, streamTest));
162         assertEquals("java.io.IOException: " + SERIALIZE_IO_EXCEPTION_MESSAGE, e.getMessage());
163     }
164 
165 
166     @Test
testDeserializeStream()167     public void testDeserializeStream() throws Exception {
168         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
169         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
170             oos.writeObject(iMap);
171             oos.flush();
172         }
173 
174         final ByteArrayInputStream inTest = new ByteArrayInputStream(streamReal.toByteArray());
175         final Object test = SerializationUtils.deserialize(inTest);
176         assertNotNull(test);
177         assertTrue(test instanceof HashMap<?, ?>);
178         assertNotSame(test, iMap);
179         final HashMap<?, ?> testMap = (HashMap<?, ?>) test;
180         assertEquals(iString, testMap.get("FOO"));
181         assertNotSame(iString, testMap.get("FOO"));
182         assertEquals(iInteger, testMap.get("BAR"));
183         assertNotSame(iInteger, testMap.get("BAR"));
184         assertEquals(iMap, testMap);
185     }
186 
187     @Test
testDeserializeClassCastException()188     public void testDeserializeClassCastException() {
189         final String value = "Hello";
190         final byte[] serialized = SerializationUtils.serialize(value);
191         assertEquals(value, SerializationUtils.deserialize(serialized));
192         assertThrows(ClassCastException.class, () -> {
193             // Causes ClassCastException in call site, not in SerializationUtils.deserialize
194             @SuppressWarnings("unused") // needed to cause Exception
195             final Integer i = SerializationUtils.deserialize(serialized);
196         });
197     }
198 
199     @Test
testDeserializeStreamOfNull()200     public void testDeserializeStreamOfNull() throws Exception {
201         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
202         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
203             oos.writeObject(null);
204             oos.flush();
205         }
206 
207         final ByteArrayInputStream inTest = new ByteArrayInputStream(streamReal.toByteArray());
208         final Object test = SerializationUtils.deserialize(inTest);
209         assertNull(test);
210     }
211 
212     @Test
testDeserializeStreamNull()213     public void testDeserializeStreamNull() {
214         assertThrows(NullPointerException.class, () -> SerializationUtils.deserialize((InputStream) null));
215     }
216 
217     @Test
testDeserializeStreamBadStream()218     public void testDeserializeStreamBadStream() {
219         assertThrows(SerializationException.class,
220                 () -> SerializationUtils.deserialize(new ByteArrayInputStream(new byte[0])));
221     }
222 
223     @Test
testDeserializeStreamClassNotFound()224     public void testDeserializeStreamClassNotFound() throws Exception {
225         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
226         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
227             oos.writeObject(new ClassNotFoundSerialization());
228             oos.flush();
229         }
230 
231         final ByteArrayInputStream inTest = new ByteArrayInputStream(streamReal.toByteArray());
232         final SerializationException se = assertThrows(SerializationException.class, () -> SerializationUtils.deserialize(inTest));
233         assertEquals("java.lang.ClassNotFoundException: " + CLASS_NOT_FOUND_MESSAGE, se.getMessage());
234     }
235 
236     @Test
testRoundtrip()237     public void testRoundtrip() {
238         final HashMap<Object, Object> newMap = SerializationUtils.roundtrip(iMap);
239         assertEquals(iMap, newMap);
240     }
241 
242     @Test
testSerializeBytes()243     public void testSerializeBytes() throws Exception {
244         final byte[] testBytes = SerializationUtils.serialize(iMap);
245 
246         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
247         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
248             oos.writeObject(iMap);
249             oos.flush();
250         }
251 
252         final byte[] realBytes = streamReal.toByteArray();
253         assertEquals(testBytes.length, realBytes.length);
254         assertArrayEquals(realBytes, testBytes);
255     }
256 
257     @Test
testSerializeBytesUnserializable()258     public void testSerializeBytesUnserializable() {
259         iMap.put(new Object(), new Object());
260         assertThrows(SerializationException.class, () -> SerializationUtils.serialize(iMap));
261     }
262 
263     @Test
testSerializeBytesNull()264     public void testSerializeBytesNull() throws Exception {
265         final byte[] testBytes = SerializationUtils.serialize(null);
266 
267         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
268         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
269             oos.writeObject(null);
270             oos.flush();
271         }
272 
273         final byte[] realBytes = streamReal.toByteArray();
274         assertEquals(testBytes.length, realBytes.length);
275         assertArrayEquals(realBytes, testBytes);
276     }
277 
278 
279     @Test
testDeserializeBytes()280     public void testDeserializeBytes() throws Exception {
281         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
282         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
283             oos.writeObject(iMap);
284             oos.flush();
285         }
286 
287         final Object test = SerializationUtils.deserialize(streamReal.toByteArray());
288         assertNotNull(test);
289         assertTrue(test instanceof HashMap<?, ?>);
290         assertNotSame(test, iMap);
291         final HashMap<?, ?> testMap = (HashMap<?, ?>) test;
292         assertEquals(iString, testMap.get("FOO"));
293         assertNotSame(iString, testMap.get("FOO"));
294         assertEquals(iInteger, testMap.get("BAR"));
295         assertNotSame(iInteger, testMap.get("BAR"));
296         assertEquals(iMap, testMap);
297     }
298 
299     @Test
testDeserializeBytesOfNull()300     public void testDeserializeBytesOfNull() throws Exception {
301         final ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
302         try (ObjectOutputStream oos = new ObjectOutputStream(streamReal)) {
303             oos.writeObject(null);
304             oos.flush();
305         }
306 
307         final Object test = SerializationUtils.deserialize(streamReal.toByteArray());
308         assertNull(test);
309     }
310 
311     @Test
testDeserializeBytesNull()312     public void testDeserializeBytesNull() {
313         assertThrows(NullPointerException.class, () -> SerializationUtils.deserialize((byte[]) null));
314     }
315 
316     @Test
testDeserializeBytesBadStream()317     public void testDeserializeBytesBadStream() {
318         assertThrows(SerializationException.class, () -> SerializationUtils.deserialize(new byte[0]));
319     }
320 
321 
322     @Test
testClone()323     public void testClone() {
324         final Object test = SerializationUtils.clone(iMap);
325         assertNotNull(test);
326         assertTrue(test instanceof HashMap<?, ?>);
327         assertNotSame(test, iMap);
328         final HashMap<?, ?> testMap = (HashMap<?, ?>) test;
329         assertEquals(iString, testMap.get("FOO"));
330         assertNotSame(iString, testMap.get("FOO"));
331         assertEquals(iInteger, testMap.get("BAR"));
332         assertNotSame(iInteger, testMap.get("BAR"));
333         assertEquals(iMap, testMap);
334     }
335 
336     @Test
testCloneNull()337     public void testCloneNull() {
338         final Object test = SerializationUtils.clone(null);
339         assertNull(test);
340     }
341 
342     @Test
testCloneUnserializable()343     public void testCloneUnserializable() {
344         iMap.put(new Object(), new Object());
345         assertThrows(SerializationException.class, () -> SerializationUtils.clone(iMap));
346     }
347 
348     @Test
testPrimitiveTypeClassSerialization()349     public void testPrimitiveTypeClassSerialization() {
350         final Class<?>[] primitiveTypes = { byte.class, short.class, int.class, long.class, float.class, double.class,
351                 boolean.class, char.class, void.class };
352 
353         for (final Class<?> primitiveType : primitiveTypes) {
354             final Class<?> clone = SerializationUtils.clone(primitiveType);
355             assertEquals(primitiveType, clone);
356         }
357     }
358 
359 }
360 
361 class ClassNotFoundSerialization implements Serializable {
362 
363     private static final long serialVersionUID = 1L;
364 
readObject(final ObjectInputStream in)365     private void readObject(final ObjectInputStream in) throws ClassNotFoundException    {
366         throw new ClassNotFoundException(SerializationUtilsTest.CLASS_NOT_FOUND_MESSAGE);
367     }
368 }
369