aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Desprez <jdesprez@google.com>2017-06-19 19:05:26 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-06-19 19:05:27 +0000
commitd96fa8d2f5676a2576e5152317e8837a93942dd1 (patch)
tree34eee5ac924cb82d49b517e9ea9eb8f070c44910
parent3ebf8320cf4513d07bd67f51f11b5d409500dea2 (diff)
parent265766c7ac8bf5ede81dde1e1f833267cfa4cd25 (diff)
downloadtradefederation-d96fa8d2f5676a2576e5152317e8837a93942dd1.tar.gz
Merge "Make IBuildInfo serializable" into oc-dev
-rw-r--r--src/com/android/tradefed/build/IBuildInfo.java7
-rw-r--r--src/com/android/tradefed/build/VersionedFile.java7
-rw-r--r--src/com/android/tradefed/util/MultiMap.java7
-rw-r--r--src/com/android/tradefed/util/SerializationUtil.java80
-rw-r--r--tests/src/com/android/tradefed/UnitTests.java2
-rw-r--r--tests/src/com/android/tradefed/build/BuildInfoTest.java20
-rw-r--r--tests/src/com/android/tradefed/build/DeviceFolderBuildInfoTest.java24
-rw-r--r--tests/src/com/android/tradefed/util/SerializationUtilTest.java128
8 files changed, 261 insertions, 14 deletions
diff --git a/src/com/android/tradefed/build/IBuildInfo.java b/src/com/android/tradefed/build/IBuildInfo.java
index 385e1bf75..f88e443e4 100644
--- a/src/com/android/tradefed/build/IBuildInfo.java
+++ b/src/com/android/tradefed/build/IBuildInfo.java
@@ -18,13 +18,12 @@ package com.android.tradefed.build;
import com.android.tradefed.device.ITestDevice;
import java.io.File;
+import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
-/**
- * Holds information about the build under test.
- */
-public interface IBuildInfo {
+/** Holds information about the build under test. */
+public interface IBuildInfo extends Serializable {
/**
* Default value when build ID is unknown.
diff --git a/src/com/android/tradefed/build/VersionedFile.java b/src/com/android/tradefed/build/VersionedFile.java
index 24bd031ad..2c71b07d4 100644
--- a/src/com/android/tradefed/build/VersionedFile.java
+++ b/src/com/android/tradefed/build/VersionedFile.java
@@ -16,11 +16,10 @@
package com.android.tradefed.build;
import java.io.File;
+import java.io.Serializable;
-/**
- * Data structure representing a file that has an associated version.
- */
-public class VersionedFile {
+/** Data structure representing a file that has an associated version. */
+public class VersionedFile implements Serializable {
private final File mFile;
private final String mVersion;
diff --git a/src/com/android/tradefed/util/MultiMap.java b/src/com/android/tradefed/util/MultiMap.java
index 16517bb48..1123e6d64 100644
--- a/src/com/android/tradefed/util/MultiMap.java
+++ b/src/com/android/tradefed/util/MultiMap.java
@@ -17,16 +17,15 @@ package com.android.tradefed.util;
import com.google.common.base.Objects;
+import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-/**
- * A {@link Map} that supports multiple values per key.
- */
-public class MultiMap<K, V> {
+/** A {@link Map} that supports multiple values per key. */
+public class MultiMap<K, V> implements Serializable {
private final Map<K, List<V>> mInternalMap;
diff --git a/src/com/android/tradefed/util/SerializationUtil.java b/src/com/android/tradefed/util/SerializationUtil.java
new file mode 100644
index 000000000..0c991fffd
--- /dev/null
+++ b/src/com/android/tradefed/util/SerializationUtil.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tradefed.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/** Utility to serialize/deserialize an object that implements {@link Serializable}. */
+public class SerializationUtil {
+
+ /**
+ * Serialize a object that implements {@link Serializable}.
+ *
+ * @param o the object to serialize.
+ * @return the {@link File} where the object was serialized.
+ * @throws IOException if serialization fails.
+ */
+ public static File serialize(Serializable o) throws IOException {
+ File tmpSerialized = FileUtil.createTempFile("serial-util", ".ser");
+ FileOutputStream fileOut = null;
+ ObjectOutputStream out = null;
+ try {
+ fileOut = new FileOutputStream(tmpSerialized);
+ out = new ObjectOutputStream(fileOut);
+ out.writeObject(o);
+ } catch (IOException e) {
+ // catch in order to clean up the tmp file.
+ FileUtil.deleteFile(tmpSerialized);
+ throw e;
+ } finally {
+ StreamUtil.close(out);
+ StreamUtil.close(fileOut);
+ }
+ return tmpSerialized;
+ }
+
+ /**
+ * Deserialize an object that was serialized using {@link #serialize(Serializable)}.
+ *
+ * @param serializedFile the file where the object was serialized.
+ * @param deleteFile true if the serialized file should be deleted once deserialized.
+ * @return the Object deserialized.
+ * @throws IOException if the deserialization fails.
+ */
+ public static Object deserialize(File serializedFile, boolean deleteFile) throws IOException {
+ FileInputStream fileIn = null;
+ ObjectInputStream in = null;
+ try {
+ fileIn = new FileInputStream(serializedFile);
+ in = new ObjectInputStream(fileIn);
+ return in.readObject();
+ } catch (ClassNotFoundException cnfe) {
+ throw new RuntimeException(cnfe);
+ } finally {
+ StreamUtil.close(in);
+ StreamUtil.close(fileIn);
+ if (deleteFile) {
+ FileUtil.deleteFile(serializedFile);
+ }
+ }
+ }
+}
diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java
index 8f064a311..a30198576 100644
--- a/tests/src/com/android/tradefed/UnitTests.java
+++ b/tests/src/com/android/tradefed/UnitTests.java
@@ -186,6 +186,7 @@ import com.android.tradefed.util.PsParserTest;
import com.android.tradefed.util.QuotationAwareTokenizerTest;
import com.android.tradefed.util.RegexTrieTest;
import com.android.tradefed.util.RunUtilTest;
+import com.android.tradefed.util.SerializationUtilTest;
import com.android.tradefed.util.SimplePerfStatResultParserTest;
import com.android.tradefed.util.SimplePerfUtilTest;
import com.android.tradefed.util.SimpleStatsTest;
@@ -430,6 +431,7 @@ import org.junit.runners.Suite.SuiteClasses;
QuotationAwareTokenizerTest.class,
RegexTrieTest.class,
RunUtilTest.class,
+ SerializationUtilTest.class,
SimplePerfStatResultParserTest.class,
SimplePerfUtilTest.class,
SimpleStatsTest.class,
diff --git a/tests/src/com/android/tradefed/build/BuildInfoTest.java b/tests/src/com/android/tradefed/build/BuildInfoTest.java
index ad5b4e817..3a23d3c5a 100644
--- a/tests/src/com/android/tradefed/build/BuildInfoTest.java
+++ b/tests/src/com/android/tradefed/build/BuildInfoTest.java
@@ -15,9 +15,13 @@
*/
package com.android.tradefed.build;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.SerializationUtil;
import org.junit.After;
import org.junit.Before;
@@ -98,4 +102,18 @@ public class BuildInfoTest {
+ "build_flavor=testFlavor, branch=testBranch, serial=fakeSerial}";
assertEquals(expected, mBuildInfo.toString());
}
+
+ /**
+ * Test that all the components of {@link BuildInfo} can be serialized via the default java
+ * object serialization.
+ */
+ @Test
+ public void testSerialization() throws Exception {
+ File tmpSerialized = SerializationUtil.serialize(mBuildInfo);
+ Object o = SerializationUtil.deserialize(tmpSerialized, true);
+ assertTrue(o instanceof BuildInfo);
+ BuildInfo test = (BuildInfo) o;
+ // use the custom build info equals to check similar properties
+ assertTrue(mBuildInfo.equals(test));
+ }
}
diff --git a/tests/src/com/android/tradefed/build/DeviceFolderBuildInfoTest.java b/tests/src/com/android/tradefed/build/DeviceFolderBuildInfoTest.java
index b21d261ad..fb8c7dfa8 100644
--- a/tests/src/com/android/tradefed/build/DeviceFolderBuildInfoTest.java
+++ b/tests/src/com/android/tradefed/build/DeviceFolderBuildInfoTest.java
@@ -15,9 +15,11 @@
*/
package com.android.tradefed.build;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.SerializationUtil;
import org.junit.After;
import org.junit.Before;
@@ -90,4 +92,24 @@ public class DeviceFolderBuildInfoTest {
assertEquals(1, files.size());
assertTrue(hasFile(files, "img-version"));
}
+
+ /**
+ * Test that all the components of {@link DeviceFolderBuildInfo} can be serialized via the
+ * default java object serialization.
+ */
+ @Test
+ public void testSerialization() throws Exception {
+ DeviceBuildInfo deviceBuildInfo = new DeviceBuildInfo();
+ deviceBuildInfo.setDeviceImageFile(new File("fake"), "version 32");
+ mDeviceFolderBuildInfo.setDeviceBuild(deviceBuildInfo);
+ File tmpSerialized = SerializationUtil.serialize(mDeviceFolderBuildInfo);
+ Object o = SerializationUtil.deserialize(tmpSerialized, true);
+ assertTrue(o instanceof DeviceFolderBuildInfo);
+ DeviceFolderBuildInfo test = (DeviceFolderBuildInfo) o;
+ // use the custom build info equals to check similar properties
+ assertTrue(mDeviceFolderBuildInfo.equals(test));
+ // Both sub-build properties have been copied.
+ assertEquals("version 32", mDeviceFolderBuildInfo.getDeviceBuildId());
+ assertEquals("version 32", test.getDeviceBuildId());
+ }
}
diff --git a/tests/src/com/android/tradefed/util/SerializationUtilTest.java b/tests/src/com/android/tradefed/util/SerializationUtilTest.java
new file mode 100644
index 000000000..f992069aa
--- /dev/null
+++ b/tests/src/com/android/tradefed/util/SerializationUtilTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tradefed.util;
+
+import static org.junit.Assert.*;
+
+import com.android.tradefed.build.BuildInfo;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.NotSerializableException;
+import java.io.Serializable;
+import java.io.StreamCorruptedException;
+
+/** Unit tests for {@link SerializationUtil}. */
+@RunWith(JUnit4.class)
+public class SerializationUtilTest {
+
+ /**
+ * Test class that implements {@link Serializable} but has an attribute that is not serializable
+ */
+ public static class SerialTestClass implements Serializable {
+ public InputStream mStream;
+
+ public SerialTestClass() {
+ mStream = new ByteArrayInputStream("test".getBytes());
+ }
+ }
+
+ /** Tests that serialization and deserialization creates a similar object from the original. */
+ @Test
+ public void testSerialize_Deserialize() throws Exception {
+ BuildInfo b = new BuildInfo();
+ File tmpSerialized = SerializationUtil.serialize(b);
+ Object o = SerializationUtil.deserialize(tmpSerialized, true);
+ assertTrue(o instanceof BuildInfo);
+ BuildInfo test = (BuildInfo) o;
+ // use the custom build info equals to check similar properties
+ assertTrue(b.equals(test));
+ assertTrue(!tmpSerialized.exists());
+ }
+
+ /**
+ * Tests that serialization and deserialization creates a similar object from the original but
+ * does not delete the temporary serial file.
+ */
+ @Test
+ public void testSerialize_Deserialize_noDelete() throws Exception {
+ BuildInfo b = new BuildInfo();
+ File tmpSerialized = SerializationUtil.serialize(b);
+ try {
+ Object o = SerializationUtil.deserialize(tmpSerialized, false);
+ assertTrue(o instanceof BuildInfo);
+ BuildInfo test = (BuildInfo) o;
+ // use the custom build info equals to check similar properties
+ assertTrue(b.equals(test));
+ assertTrue(tmpSerialized.exists());
+ } finally {
+ FileUtil.deleteFile(tmpSerialized);
+ }
+ }
+
+ /** Test {@link SerializationUtil#deserialize(File, boolean)} for a non existing file. */
+ @Test
+ public void testDeserialize_noFile() {
+ try {
+ SerializationUtil.deserialize(new File("doesnotexists"), true);
+ fail("Should have thrown an exception.");
+ } catch (IOException expected) {
+ // expected
+ }
+ }
+
+ /**
+ * Test {@link SerializationUtil#deserialize(File, boolean)} for a corrupted stream, it should
+ * throw an exception.
+ */
+ @Test
+ public void testSerialize_Deserialize_corrupted() throws Exception {
+ BuildInfo b = new BuildInfo();
+ File tmpSerialized = SerializationUtil.serialize(b);
+ // add some extra data
+ FileUtil.writeToFile("oh I am corrupted", tmpSerialized, false);
+ try {
+ SerializationUtil.deserialize(tmpSerialized, true);
+ fail("Should have thrown an exception.");
+ } catch (StreamCorruptedException expected) {
+ // expected
+ }
+ // the file was still deleted as expected.
+ assertTrue(!tmpSerialized.exists());
+ }
+
+ /**
+ * Test {@link SerializationUtil#serialize(Serializable)} on an object that is not serializable
+ * because of one of its attribute. Method should throw an exception.
+ */
+ @Test
+ public void testSerialized_notSerializable() throws Exception {
+ SerialTestClass test = new SerialTestClass();
+ try {
+ SerializationUtil.serialize(test);
+ fail("Should have thrown an exception.");
+ } catch (NotSerializableException expected) {
+ // the ByteArrayInputStream attribute is not serializable.
+ assertEquals("java.io.ByteArrayInputStream", expected.getMessage());
+ }
+ }
+}