aboutsummaryrefslogtreecommitdiffstats
path: root/utils-test/src
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2018-09-13 12:40:37 -0400
committerJim Hahn <jrh3@att.com>2018-09-14 15:14:44 -0400
commit29dd6526f2a86a312578a9ee5d743e8150eacd97 (patch)
tree27ad9156366876c716572d5cef694caa17f9d0f8 /utils-test/src
parent6d8ab316a635f15816d202b3cc7bdccca67c867e (diff)
add more junit coverage to new Serializer class
Removed calls to superclass methods so that appropriate exceptions are thrown. Better comments for new tests. Removed @Ignore from tests. Removed tabs from pom. Change-Id: I97fa63951eed4c2ac5ce0a267d8da5134a2a1c71 Issue-ID: POLICY-1106 Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'utils-test/src')
-rw-r--r--utils-test/src/main/java/org/onap/policy/common/utils/io/Serializer.java64
-rw-r--r--utils-test/src/test/java/org/onap/policy/common/utils/io/SerializerTest.java280
2 files changed, 333 insertions, 11 deletions
diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/io/Serializer.java b/utils-test/src/main/java/org/onap/policy/common/utils/io/Serializer.java
index 740aad47..227b810a 100644
--- a/utils-test/src/main/java/org/onap/policy/common/utils/io/Serializer.java
+++ b/utils-test/src/main/java/org/onap/policy/common/utils/io/Serializer.java
@@ -32,6 +32,11 @@ import java.io.ObjectOutputStream;
public class Serializer {
/**
+ * Factory to access various objects. May be overridden for junit tests.
+ */
+ private static Factory factory = new Factory();
+
+ /**
* The constructor.
*/
private Serializer() {
@@ -40,15 +45,20 @@ public class Serializer {
/**
* Serializes an object into a byte array.
- *
+ *
* @param object the object to be serialized
* @return the byte array containing the serialized object
* @throws IOException if an error occurs
*/
public static <T> byte[] serialize(T object) throws IOException {
- try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
- try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
- oos.writeObject(object);
+ try (ByteArrayOutputStream out = factory.makeByteArrayOutputStream()) {
+ try (ObjectOutputStream oos = factory.makeObjectOutputStream(out)) {
+ /*
+ * writeObject() is final and mockito can't mock final methods. In
+ * addition, powermock seemed to be having difficulty with the junit test
+ * class as well, so we'll just do it with a factory method.
+ */
+ factory.writeObject(object, oos);
}
return out.toByteArray();
@@ -57,7 +67,7 @@ public class Serializer {
/**
* De-serializes an object from a byte array.
- *
+ *
* @param clazz class of object that is expected to be de-serialized
* @param data the byte array containing the serialized object
* @return the object that was de-serialized from the byte array
@@ -65,9 +75,14 @@ public class Serializer {
*/
public static <T> T deserialize(Class<T> clazz, byte[] data) throws IOException {
- try (ByteArrayInputStream in = new ByteArrayInputStream(data);
- ObjectInputStream ois = new ObjectInputStream(in)) {
- return clazz.cast(ois.readObject());
+ try (ByteArrayInputStream in = factory.makeByteArrayInputStream(data);
+ ObjectInputStream ois = factory.makeObjectInputStream(in)) {
+ /*
+ * readObject() is final and mockito can't mock final methods. In addition,
+ * powermock seemed to be having difficulty with the junit test class as well,
+ * so we'll just do it with a factory method.
+ */
+ return clazz.cast(factory.readObject(ois));
} catch (ClassNotFoundException e) {
throw new IOException(e);
@@ -77,7 +92,7 @@ public class Serializer {
/**
* Runs an object through a complete round trip, serializing and then de-serializing
* it.
- *
+ *
* @param object object to be serialized
* @return the object that was de-serialized
* @throws IOException if an error occurs
@@ -86,4 +101,35 @@ public class Serializer {
public static <T> T roundTrip(T object) throws IOException {
return (T) deserialize(object.getClass(), serialize(object));
}
+
+ /**
+ * Factory to access various objects.
+ */
+ public static class Factory {
+
+ public ByteArrayOutputStream makeByteArrayOutputStream() {
+ return new ByteArrayOutputStream();
+ }
+
+ public ByteArrayInputStream makeByteArrayInputStream(byte[] data) {
+ return new ByteArrayInputStream(data);
+ }
+
+ public ObjectOutputStream makeObjectOutputStream(ByteArrayOutputStream out) throws IOException {
+ return new ObjectOutputStream(out);
+ }
+
+ public ObjectInputStream makeObjectInputStream(ByteArrayInputStream in) throws IOException {
+ return new ObjectInputStream(in);
+ }
+
+ public void writeObject(Object object, ObjectOutputStream oos) throws IOException {
+ oos.writeObject(object);
+ }
+
+ public Object readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+ return ois.readObject();
+ }
+
+ }
}
diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/io/SerializerTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/io/SerializerTest.java
index 4d4385fc..bdf0dba9 100644
--- a/utils-test/src/test/java/org/onap/policy/common/utils/io/SerializerTest.java
+++ b/utils-test/src/test/java/org/onap/policy/common/utils/io/SerializerTest.java
@@ -7,9 +7,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,14 +21,52 @@
package org.onap.policy.common.utils.io;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
+import org.onap.policy.common.utils.io.Serializer.Factory;
+import org.powermock.reflect.Whitebox;
public class SerializerTest {
+ /**
+ * Saved and restored when tests complete. Also restored at the start of each test.
+ */
+ private static Factory saveFactory;
+
+ @BeforeClass
+ public static void setUpBeforeClass() {
+ saveFactory = Whitebox.getInternalState(Serializer.class, "factory");
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() {
+ Whitebox.setInternalState(Serializer.class, "factory", saveFactory);
+ }
+
+ @Before
+ public void setUp() {
+ setFactory(saveFactory);
+ }
+
+ @Test
+ public void testFactory() {
+ assertNotNull(saveFactory);
+ }
+
@Test
public void testSerialize() throws Exception {
MyObject obj1 = new MyObject(3);
@@ -48,6 +86,83 @@ public class SerializerTest {
}
@Test
+ public void testSerialize_ArrayCloseEx() throws Exception {
+ IOException ex = new IOException("testSerialize_ArrayCloseEx");
+
+ /*
+ * This stream will throw an exception when close() is invoked. However, close()
+ * is called twice, once by the ObjectOutputStream and once by the code we want to
+ * test. As a result, we'll have the first close() succeed and the second one
+ * fail.
+ */
+ ByteArrayOutputStream out = new ByteArrayOutputStream() {
+ private int nclose = 0;
+
+ @Override
+ public void close() throws IOException {
+ if (++nclose > 1) {
+ throw ex;
+ }
+ }
+ };
+
+ /*
+ * Use a factory that returns our special stream.
+ */
+ setFactory(new Factory() {
+ @Override
+ public ByteArrayOutputStream makeByteArrayOutputStream() {
+ return out;
+ }
+ });
+
+ assertEquals(ex, expectException(() -> Serializer.serialize(new MyObject(100))));
+ }
+
+ @Test
+ public void testSerialize_ObjectWriteEx() throws Exception {
+ IOException ex = new IOException("testSerialize_ObjectWriteEx");
+
+ /*
+ * Use a factory that throws an exception when writeObject() is invoked.
+ */
+ setFactory(new Factory() {
+ @Override
+ public void writeObject(Object object, ObjectOutputStream oos) throws IOException {
+ throw ex;
+ }
+ });
+
+ assertEquals(ex, expectException(() -> Serializer.serialize(new MyObject(110))));
+ }
+
+ @Test
+ public void testSerialize_ObjectCloseEx() throws Exception {
+ IOException ex = new IOException("testSerialize_ObjectCloseEx");
+ ObjectOutputStream oos = mock(ObjectOutputStream.class);
+ doThrow(ex).when(oos).close();
+
+ /*
+ * Use a factory that returns the mocked object which throws an exception when
+ * close() is invoked. However, we also have to override writeObject() so that it
+ * succeeds even through we're using a mock.
+ */
+ setFactory(new Factory() {
+ @Override
+ public ObjectOutputStream makeObjectOutputStream(ByteArrayOutputStream out) throws IOException {
+ return oos;
+ }
+
+ @Override
+ public void writeObject(Object object, ObjectOutputStream oos) throws IOException {
+ return;
+ }
+ });
+
+ assertEquals(ex, expectException(() -> Serializer.serialize(new MyObject(120))));
+ }
+
+ @Test
public void testDeserialize() throws Exception {
MyObject obj1 = new MyObject(3);
byte[] data = Serializer.serialize(obj1);
@@ -57,6 +172,136 @@ public class SerializerTest {
}
@Test
+ public void testDeserialize_ArrayCloseEx() throws Exception {
+ IOException ex = new IOException("testSerialize_ObjectWriteEx");
+
+ /*
+ * Use a factory that returns a stream that will throw an exception when close()
+ * is invoked. However, close() is called twice, once by the ObjectInputStream and
+ * once by the code we want to test. As a result, we'll have the first close()
+ * succeed and the second one fail.
+ */
+ setFactory(new Factory() {
+ @Override
+ public ByteArrayInputStream makeByteArrayInputStream(byte[] data) {
+ return new ByteArrayInputStream(data) {
+ private int nclose = 0;
+
+ @Override
+ public void close() throws IOException {
+ if (++nclose > 1) {
+ throw ex;
+ }
+ }
+ };
+ }
+ });
+
+ byte[] data = Serializer.serialize(new MyObject(300));
+ assertEquals(ex, expectException(() -> Serializer.deserialize(MyObject.class, data)));
+ }
+
+ @Test
+ public void testDeserialize_ObjectReadClassEx() throws Exception {
+ ClassNotFoundException ex = new ClassNotFoundException("testDeserialize_ObjectReadClassEx");
+
+ /*
+ * Use a factory that throws a ClassNotFoundException when readObject() is
+ * invoked.
+ */
+ setFactory(new Factory() {
+ @Override
+ public Object readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+ throw ex;
+ }
+ });
+
+ byte[] data = Serializer.serialize(new MyObject(305));
+
+ Exception exwrap = expectException(() -> Serializer.deserialize(MyObject.class, data));
+ assertTrue(exwrap instanceof IOException);
+ assertNotNull(exwrap.getCause());
+ assertEquals(ex, exwrap.getCause());
+ }
+
+ @Test
+ public void testDeserialize_ObjectReadEx() throws Exception {
+ IOException ex = new IOException("testDeserialize_ObjectReadEx");
+
+ /*
+ * Use a factory that throws an IOException when readObject() is invoked.
+ */
+ setFactory(new Factory() {
+ @Override
+ public Object readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+ throw ex;
+ }
+ });
+
+ byte[] data = Serializer.serialize(new MyObject(310));
+ assertEquals(ex, expectException(() -> Serializer.deserialize(MyObject.class, data)));
+ }
+
+ @Test
+ public void testDeserialize_ObjectCloseEx() throws Exception {
+ IOException ex = new IOException("testDeserialize_ObjectCloseEx");
+
+ /*
+ * Use a factory that returns an ObjectInputStream that throws an exception when
+ * close() is invoked.
+ */
+ setFactory(new Factory() {
+ @Override
+ public ObjectInputStream makeObjectInputStream(ByteArrayInputStream in) throws IOException {
+ return new ObjectInputStream(in) {
+ @Override
+ public void close() throws IOException {
+ throw ex;
+ }
+ };
+ }
+ });
+
+ byte[] data = Serializer.serialize(new MyObject(320));
+ assertEquals(ex, expectException(() -> Serializer.deserialize(MyObject.class, data)));
+ }
+
+ @Test
+ public void testDeserialize_BothCloseEx() throws Exception {
+ IOException ex = new IOException("testDeserialize_BothCloseEx");
+ IOException ex2 = new IOException("testDeserialize_BothCloseEx_2");
+
+ /*
+ * Use a factory that returns input streams, both of which throw exceptions when
+ * close() is invoked.
+ */
+ setFactory(new Factory() {
+ @Override
+ public ByteArrayInputStream makeByteArrayInputStream(byte[] data) {
+ return new ByteArrayInputStream(data) {
+ @Override
+ public void close() throws IOException {
+ throw ex;
+ }
+ };
+ }
+
+ @Override
+ public ObjectInputStream makeObjectInputStream(ByteArrayInputStream in) throws IOException {
+ return new ObjectInputStream(in) {
+ @Override
+ public void close() throws IOException {
+ throw ex2;
+ }
+ };
+ }
+ });
+
+ byte[] data = Serializer.serialize(new MyObject(330));
+ assertEquals(ex2, expectException(() -> Serializer.deserialize(MyObject.class, data)));
+ }
+
+ @Test
public void testRoundTrip() throws Exception {
MyObject obj1 = new MyObject(3);
@@ -70,6 +315,37 @@ public class SerializerTest {
}
/**
+ * Sets a new factory in the Serializer.
+ *
+ * @param factory new factory to be set
+ */
+ private void setFactory(Factory factory) {
+ Whitebox.setInternalState(Serializer.class, "factory", factory);
+ }
+
+ /**
+ * Applies a function, which is expected to throw an exception.
+ *
+ * @param func the function to apply
+ * @return the exception thrown by the function, or {@code null} if it did not throw
+ * an exception
+ */
+ private Exception expectException(RunnerWithEx func) {
+ try {
+ func.apply();
+ return null;
+
+ } catch (Exception ex) {
+ return ex;
+ }
+ }
+
+ @FunctionalInterface
+ private static interface RunnerWithEx {
+ public void apply() throws Exception;
+ }
+
+ /**
* Simple, serializable object.
*/
public static class MyObject implements Serializable {