| /* |
| * Copyright (C) 2009 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 android.os.cts; |
| |
| import java.io.FileDescriptor; |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.TimeoutException; |
| |
| import android.app.Service; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.ServiceConnection; |
| import android.content.pm.Signature; |
| import android.os.BadParcelableException; |
| import android.os.Binder; |
| import android.os.Bundle; |
| import android.os.IBinder; |
| import android.os.IInterface; |
| import android.os.Parcel; |
| import android.os.ParcelFileDescriptor; |
| import android.os.Parcelable; |
| import android.platform.test.annotations.AsbSecurityTest; |
| import android.test.AndroidTestCase; |
| import android.util.Log; |
| import android.util.SparseArray; |
| import android.util.SparseBooleanArray; |
| |
| import com.google.common.util.concurrent.AbstractFuture; |
| |
| import static org.junit.Assert.assertArrayEquals; |
| import static org.junit.Assert.assertThrows; |
| |
| public class ParcelTest extends AndroidTestCase { |
| |
| public void testObtain() { |
| Parcel p1 = Parcel.obtain(); |
| assertNotNull(p1); |
| Parcel p2 = Parcel.obtain(); |
| assertNotNull(p2); |
| Parcel p3 = Parcel.obtain(); |
| assertNotNull(p3); |
| Parcel p4 = Parcel.obtain(); |
| assertNotNull(p4); |
| Parcel p5 = Parcel.obtain(); |
| assertNotNull(p5); |
| Parcel p6 = Parcel.obtain(); |
| assertNotNull(p6); |
| Parcel p7 = Parcel.obtain(); |
| assertNotNull(p7); |
| |
| p1.recycle(); |
| p2.recycle(); |
| p3.recycle(); |
| p4.recycle(); |
| p5.recycle(); |
| p6.recycle(); |
| p7.recycle(); |
| } |
| |
| public void testAppendFrom() { |
| Parcel p; |
| Parcel p2; |
| int d1; |
| int d2; |
| |
| p = Parcel.obtain(); |
| d1 = p.dataPosition(); |
| p.writeInt(7); |
| p.writeInt(5); |
| d2 = p.dataPosition(); |
| p2 = Parcel.obtain(); |
| p2.appendFrom(p, d1, d2 - d1); |
| p2.setDataPosition(0); |
| assertEquals(7, p2.readInt()); |
| assertEquals(5, p2.readInt()); |
| p2.recycle(); |
| p.recycle(); |
| } |
| |
| public void testDataAvail() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| p.writeInt(7); // size 4 |
| p.writeInt(5); // size 4 |
| p.writeLong(7L); // size 8 |
| p.writeString("7L"); // size 12 |
| p.setDataPosition(0); |
| assertEquals(p.dataSize(), p.dataAvail()); |
| p.readInt(); |
| assertEquals(p.dataSize() - p.dataPosition(), p.dataAvail()); |
| p.readInt(); |
| assertEquals(p.dataSize() - p.dataPosition(), p.dataAvail()); |
| p.readLong(); |
| assertEquals(p.dataSize() - p.dataPosition(), p.dataAvail()); |
| p.readString(); |
| assertEquals(p.dataSize() - p.dataPosition(), p.dataAvail()); |
| p.recycle(); |
| } |
| |
| public void testDataCapacity() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| assertEquals(0, p.dataCapacity()); |
| p.writeInt(7); // size 4 |
| int dC1 = p.dataCapacity(); |
| p.writeDouble(2.19); |
| int dC2 = p.dataCapacity(); |
| assertTrue(dC2 >= dC1); |
| p.recycle(); |
| } |
| |
| public void testSetDataCapacity() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| assertEquals(0, p.dataCapacity()); |
| p.setDataCapacity(2); |
| assertEquals(2, p.dataCapacity()); |
| p.setDataCapacity(1); |
| assertEquals(2, p.dataCapacity()); |
| p.setDataCapacity(3); |
| assertEquals(3, p.dataCapacity()); |
| p.recycle(); |
| } |
| |
| public void testDataPosition() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| assertEquals(0, p.dataPosition()); |
| p.writeInt(7); // size 4 |
| int dP1 = p.dataPosition(); |
| p.writeLong(7L); // size 8 |
| int dP2 = p.dataPosition(); |
| assertTrue(dP2 > dP1); |
| p.recycle(); |
| } |
| |
| public void testSetDataPosition() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| assertEquals(0, p.dataSize()); |
| assertEquals(0, p.dataPosition()); |
| p.setDataPosition(4); |
| assertEquals(4, p.dataPosition()); |
| p.setDataPosition(7); |
| assertEquals(7, p.dataPosition()); |
| p.setDataPosition(0); |
| p.writeInt(7); |
| assertEquals(4, p.dataSize()); |
| p.setDataPosition(4); |
| assertEquals(4, p.dataPosition()); |
| p.setDataPosition(7); |
| assertEquals(7, p.dataPosition()); |
| p.recycle(); |
| } |
| |
| public void testDataSize() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| assertEquals(0, p.dataSize()); |
| p.writeInt(7); // size 4 |
| assertEquals(4, p.dataSize()); |
| p.writeInt(5); // size 4 |
| assertEquals(8, p.dataSize()); |
| p.writeLong(7L); // size 8 |
| assertEquals(16, p.dataSize()); |
| p.recycle(); |
| } |
| |
| public void testSetDataSize() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| assertEquals(0, p.dataSize()); |
| p.setDataSize(5); |
| assertEquals(5, p.dataSize()); |
| p.setDataSize(3); |
| assertEquals(3, p.dataSize()); |
| |
| p.writeInt(3); |
| assertEquals(4, p.dataSize()); |
| p.setDataSize(5); |
| assertEquals(5, p.dataSize()); |
| p.setDataSize(3); |
| assertEquals(3, p.dataSize()); |
| p.recycle(); |
| } |
| |
| public void testObtainWithBinder() { |
| Parcel p = Parcel.obtain(new Binder("anything")); |
| // testing does not throw an exception, Parcel still works |
| |
| final int kTest = 17; |
| p.writeInt(kTest); |
| p.setDataPosition(0); |
| assertEquals(kTest, p.readInt()); |
| |
| p.recycle(); |
| } |
| |
| public void testEnforceInterface() { |
| Parcel p; |
| String s = "IBinder interface token"; |
| |
| p = Parcel.obtain(); |
| p.writeInterfaceToken(s); |
| p.setDataPosition(0); |
| try { |
| p.enforceInterface(""); |
| fail("Should throw an SecurityException"); |
| } catch (SecurityException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInterfaceToken(s); |
| p.setDataPosition(0); |
| p.enforceInterface(s); |
| p.recycle(); |
| } |
| |
| public void testEnforceNoDataAvail(){ |
| final Parcel p = Parcel.obtain(); |
| p.writeInt(1); |
| p.writeString("test"); |
| |
| p.setDataPosition(0); |
| p.readInt(); |
| Throwable error = assertThrows(BadParcelableException.class, () -> p.enforceNoDataAvail()); |
| assertTrue(error.getMessage().contains("Parcel data not fully consumed")); |
| |
| p.readString(); |
| p.enforceNoDataAvail(); |
| p.recycle(); |
| } |
| |
| public void testMarshall() { |
| final byte[] c = {Byte.MAX_VALUE, (byte) 111, (byte) 11, (byte) 1, (byte) 0, |
| (byte) -1, (byte) -11, (byte) -111, Byte.MIN_VALUE}; |
| |
| Parcel p1 = Parcel.obtain(); |
| p1.writeByteArray(c); |
| p1.setDataPosition(0); |
| byte[] d1 = p1.marshall(); |
| |
| Parcel p2 = Parcel.obtain(); |
| p2.unmarshall(d1, 0, d1.length); |
| p2.setDataPosition(0); |
| byte[] d2 = new byte[c.length]; |
| p2.readByteArray(d2); |
| |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d2[i]); |
| } |
| |
| p1.recycle(); |
| p2.recycle(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testReadValue() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| // test null |
| p = Parcel.obtain(); |
| p.writeValue(null); |
| p.setDataPosition(0); |
| assertNull(p.readValue(mcl)); |
| p.recycle(); |
| |
| // test String |
| p = Parcel.obtain(); |
| p.writeValue("String"); |
| p.setDataPosition(0); |
| assertEquals("String", p.readValue(mcl)); |
| p.recycle(); |
| |
| // test Integer |
| p = Parcel.obtain(); |
| p.writeValue(Integer.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Integer.MAX_VALUE, p.readValue(mcl)); |
| p.recycle(); |
| |
| // test Map |
| HashMap map = new HashMap(); |
| HashMap map2; |
| map.put("string", "String"); |
| map.put("int", Integer.MAX_VALUE); |
| map.put("boolean", true); |
| p = Parcel.obtain(); |
| p.writeValue(map); |
| p.setDataPosition(0); |
| map2 = (HashMap) p.readValue(mcl); |
| assertNotNull(map2); |
| assertEquals(map.size(), map2.size()); |
| assertEquals("String", map.get("string")); |
| assertEquals(Integer.MAX_VALUE, map.get("int")); |
| assertEquals(true, map.get("boolean")); |
| p.recycle(); |
| |
| // test Bundle |
| Bundle bundle = new Bundle(); |
| bundle.putBoolean("boolean", true); |
| bundle.putInt("int", Integer.MAX_VALUE); |
| bundle.putString("string", "String"); |
| Bundle bundle2; |
| p = Parcel.obtain(); |
| p.writeValue(bundle); |
| p.setDataPosition(0); |
| bundle2 = (Bundle) p.readValue(mcl); |
| assertNotNull(bundle2); |
| assertEquals(true, bundle2.getBoolean("boolean")); |
| assertEquals(Integer.MAX_VALUE, bundle2.getInt("int")); |
| assertEquals("String", bundle2.getString("string")); |
| p.recycle(); |
| |
| // test Parcelable |
| final String signatureString = "1234567890abcdef"; |
| Signature s = new Signature(signatureString); |
| p = Parcel.obtain(); |
| p.writeValue(s); |
| p.setDataPosition(0); |
| assertEquals(s, p.readValue(mcl)); |
| p.recycle(); |
| |
| // test Short |
| p = Parcel.obtain(); |
| p.writeValue(Short.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Short.MAX_VALUE, p.readValue(mcl)); |
| p.recycle(); |
| |
| // test Long |
| p = Parcel.obtain(); |
| p.writeValue(Long.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Long.MAX_VALUE, p.readValue(mcl)); |
| p.recycle(); |
| |
| // test Float |
| p = Parcel.obtain(); |
| p.writeValue(Float.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Float.MAX_VALUE, p.readValue(mcl)); |
| p.recycle(); |
| |
| // test Double |
| p = Parcel.obtain(); |
| p.writeValue(Double.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Double.MAX_VALUE, p.readValue(mcl)); |
| p.recycle(); |
| |
| // test Boolean |
| p = Parcel.obtain(); |
| p.writeValue(true); |
| p.writeValue(false); |
| p.setDataPosition(0); |
| assertTrue((Boolean) p.readValue(mcl)); |
| assertFalse((Boolean) p.readValue(mcl)); |
| p.recycle(); |
| |
| // test CharSequence |
| p = Parcel.obtain(); |
| p.writeValue((CharSequence) "CharSequence"); |
| p.setDataPosition(0); |
| assertEquals("CharSequence", p.readValue(mcl)); |
| p.recycle(); |
| |
| // test List |
| ArrayList arrayList2 = new ArrayList(); |
| arrayList2.add(Integer.MAX_VALUE); |
| arrayList2.add(true); |
| arrayList2.add(Long.MAX_VALUE); |
| ArrayList arrayList = new ArrayList(); |
| p = Parcel.obtain(); |
| p.writeValue(arrayList2); |
| p.setDataPosition(0); |
| assertEquals(0, arrayList.size()); |
| arrayList = (ArrayList) p.readValue(mcl); |
| assertEquals(3, arrayList.size()); |
| for (int i = 0; i < arrayList.size(); i++) { |
| assertEquals(arrayList.get(i), arrayList2.get(i)); |
| } |
| p.recycle(); |
| |
| // test SparseArray |
| SparseArray<Object> sparseArray = new SparseArray<Object>(); |
| sparseArray.put(3, "String"); |
| sparseArray.put(2, Long.MAX_VALUE); |
| sparseArray.put(4, Float.MAX_VALUE); |
| sparseArray.put(0, Integer.MAX_VALUE); |
| sparseArray.put(1, true); |
| sparseArray.put(10, true); |
| SparseArray<Object> sparseArray2; |
| p = Parcel.obtain(); |
| p.writeValue(sparseArray); |
| p.setDataPosition(0); |
| sparseArray2 = (SparseArray<Object>) p.readValue(mcl); |
| assertNotNull(sparseArray2); |
| assertEquals(sparseArray.size(), sparseArray2.size()); |
| assertEquals(sparseArray.get(0), sparseArray2.get(0)); |
| assertEquals(sparseArray.get(1), sparseArray2.get(1)); |
| assertEquals(sparseArray.get(2), sparseArray2.get(2)); |
| assertEquals(sparseArray.get(3), sparseArray2.get(3)); |
| assertEquals(sparseArray.get(4), sparseArray2.get(4)); |
| assertEquals(sparseArray.get(10), sparseArray2.get(10)); |
| p.recycle(); |
| |
| // test boolean[] |
| boolean[] booleanArray = {true, false, true, false}; |
| boolean[] booleanArray2 = new boolean[booleanArray.length]; |
| p = Parcel.obtain(); |
| p.writeValue(booleanArray); |
| p.setDataPosition(0); |
| booleanArray2 = (boolean[]) p.readValue(mcl); |
| for (int i = 0; i < booleanArray.length; i++) { |
| assertEquals(booleanArray[i], booleanArray2[i]); |
| } |
| p.recycle(); |
| |
| // test byte[] |
| byte[] byteArray = {Byte.MAX_VALUE, (byte) 111, (byte) 11, (byte) 1, (byte) 0, |
| (byte) -1, (byte) -11, (byte) -111, Byte.MIN_VALUE}; |
| byte[] byteArray2 = new byte[byteArray.length]; |
| p = Parcel.obtain(); |
| p.writeValue(byteArray); |
| p.setDataPosition(0); |
| byteArray2 = (byte[]) p.readValue(mcl); |
| for (int i = 0; i < byteArray.length; i++) { |
| assertEquals(byteArray[i], byteArray2[i]); |
| } |
| p.recycle(); |
| |
| // test string[] |
| String[] stringArray = {"", |
| "a", |
| "Hello, Android!", |
| "A long string that is used to test the api readStringArray(),"}; |
| String[] stringArray2 = new String[stringArray.length]; |
| p = Parcel.obtain(); |
| p.writeValue(stringArray); |
| p.setDataPosition(0); |
| stringArray2 = (String[]) p.readValue(mcl); |
| for (int i = 0; i < stringArray.length; i++) { |
| assertEquals(stringArray[i], stringArray2[i]); |
| } |
| p.recycle(); |
| |
| // test IBinder |
| Binder binder; |
| Binder binder2 = new Binder(); |
| p = Parcel.obtain(); |
| p.writeValue(binder2); |
| p.setDataPosition(0); |
| binder = (Binder) p.readValue(mcl); |
| assertEquals(binder2, binder); |
| p.recycle(); |
| |
| // test Parcelable[] |
| Signature[] signatures = {new Signature("1234"), |
| new Signature("ABCD"), |
| new Signature("abcd")}; |
| Parcelable[] signatures2; |
| p = Parcel.obtain(); |
| p.writeValue(signatures); |
| p.setDataPosition(0); |
| signatures2 = (Parcelable[]) p.readValue(mcl); |
| for (int i = 0; i < signatures.length; i++) { |
| assertEquals(signatures[i], signatures2[i]); |
| } |
| p.recycle(); |
| |
| // test Object |
| Object[] objects = new Object[5]; |
| objects[0] = Integer.MAX_VALUE; |
| objects[1] = true; |
| objects[2] = Long.MAX_VALUE; |
| objects[3] = "String"; |
| objects[4] = Float.MAX_VALUE; |
| Object[] objects2; |
| p = Parcel.obtain(); |
| p.writeValue(objects); |
| p.setDataPosition(0); |
| objects2 = (Object[]) p.readValue(mcl); |
| assertNotNull(objects2); |
| for (int i = 0; i < objects2.length; i++) { |
| assertEquals(objects[i], objects2[i]); |
| } |
| p.recycle(); |
| |
| // test int[] |
| int[] intArray = {111, 11, 1, 0, -1, -11, -111}; |
| int[] intArray2 = new int[intArray.length]; |
| p = Parcel.obtain(); |
| p.writeValue(intArray); |
| p.setDataPosition(0); |
| intArray2= (int[]) p.readValue(mcl); |
| assertNotNull(intArray2); |
| for (int i = 0; i < intArray2.length; i++) { |
| assertEquals(intArray[i], intArray2[i]); |
| } |
| p.recycle(); |
| |
| // test long[] |
| long[] longArray = {111L, 11L, 1L, 0L, -1L, -11L, -111L}; |
| long[] longArray2 = new long[longArray.length]; |
| p = Parcel.obtain(); |
| p.writeValue(longArray); |
| p.setDataPosition(0); |
| longArray2= (long[]) p.readValue(mcl); |
| assertNotNull(longArray2); |
| for (int i = 0; i < longArray2.length; i++) { |
| assertEquals(longArray[i], longArray2[i]); |
| } |
| p.recycle(); |
| |
| // test byte |
| p = Parcel.obtain(); |
| p.writeValue(Byte.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Byte.MAX_VALUE, p.readValue(mcl)); |
| p.recycle(); |
| |
| // test Serializable |
| p = Parcel.obtain(); |
| p.writeValue((Serializable) "Serializable"); |
| p.setDataPosition(0); |
| assertEquals("Serializable", p.readValue(mcl)); |
| p.recycle(); |
| } |
| |
| public void testReadByte() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| p.writeByte((byte) 0); |
| p.setDataPosition(0); |
| assertEquals((byte) 0, p.readByte()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeByte((byte) 1); |
| p.setDataPosition(0); |
| assertEquals((byte) 1, p.readByte()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeByte((byte) -1); |
| p.setDataPosition(0); |
| assertEquals((byte) -1, p.readByte()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeByte(Byte.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Byte.MAX_VALUE, p.readByte()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeByte(Byte.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Byte.MIN_VALUE, p.readByte()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeByte(Byte.MAX_VALUE); |
| p.writeByte((byte) 11); |
| p.writeByte((byte) 1); |
| p.writeByte((byte) 0); |
| p.writeByte((byte) -1); |
| p.writeByte((byte) -11); |
| p.writeByte(Byte.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Byte.MAX_VALUE, p.readByte()); |
| assertEquals((byte) 11, p.readByte()); |
| assertEquals((byte) 1, p.readByte()); |
| assertEquals((byte) 0, p.readByte()); |
| assertEquals((byte) -1, p.readByte()); |
| assertEquals((byte) -11, p.readByte()); |
| assertEquals(Byte.MIN_VALUE, p.readByte()); |
| p.recycle(); |
| } |
| |
| public void testReadByteArray() { |
| Parcel p; |
| |
| byte[] a = {(byte) 21}; |
| byte[] b = new byte[a.length]; |
| |
| byte[] c = {Byte.MAX_VALUE, (byte) 111, (byte) 11, (byte) 1, (byte) 0, |
| (byte) -1, (byte) -11, (byte) -111, Byte.MIN_VALUE}; |
| byte[] d = new byte[c.length]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeByteArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readByteArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readByteArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write byte array with length: 1 |
| p = Parcel.obtain(); |
| p.writeByteArray(a); |
| p.setDataPosition(0); |
| try { |
| p.readByteArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readByteArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write byte array with length: 9 |
| p = Parcel.obtain(); |
| p.writeByteArray(c); |
| p.setDataPosition(0); |
| try { |
| p.readByteArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readByteArray(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| |
| // Test array bounds checks (null already checked above). |
| p = Parcel.obtain(); |
| try { |
| p.writeByteArray(c, -1, 1); // Negative offset. |
| fail(); |
| } catch (RuntimeException expected) { |
| } |
| try { |
| p.writeByteArray(c, 0, -1); // Negative count. |
| fail(); |
| } catch (RuntimeException expected) { |
| } |
| try { |
| p.writeByteArray(c, c.length + 1, 1); // High offset. |
| fail(); |
| } catch (RuntimeException expected) { |
| } |
| try { |
| p.writeByteArray(c, 0, c.length + 1); // High count. |
| fail(); |
| } catch (RuntimeException expected) { |
| } |
| p.recycle(); |
| } |
| |
| public void testWriteByteArray() { |
| Parcel p; |
| |
| byte[] a = {(byte) 21}; |
| byte[] b = new byte[a.length]; |
| |
| byte[] c = {Byte.MAX_VALUE, (byte) 111, (byte) 11, (byte) 1, (byte) 0, |
| (byte) -1, (byte) -11, (byte) -111, Byte.MIN_VALUE}; |
| byte[] d = new byte[c.length - 2]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeByteArray(null, 0, 2); |
| p.setDataPosition(0); |
| try { |
| p.readByteArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readByteArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test with wrong offset and length |
| p = Parcel.obtain(); |
| try { |
| p.writeByteArray(a, 0, 2); |
| fail("Should throw a ArrayIndexOutOfBoundsException"); |
| } catch (ArrayIndexOutOfBoundsException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| try { |
| p.writeByteArray(a, -1, 1); |
| fail("Should throw a ArrayIndexOutOfBoundsException"); |
| } catch (ArrayIndexOutOfBoundsException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| try { |
| p.writeByteArray(a, 0, -1); |
| fail("Should throw a ArrayIndexOutOfBoundsException"); |
| } catch (ArrayIndexOutOfBoundsException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write byte array with length: 1 |
| p = Parcel.obtain(); |
| p.writeByteArray(a, 0 , 1); |
| p.setDataPosition(0); |
| try { |
| p.readByteArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readByteArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write byte array with offset: 1, length: 7 |
| p = Parcel.obtain(); |
| p.writeByteArray(c, 1, 7); |
| p.setDataPosition(0); |
| try { |
| p.readByteArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| d = new byte[c.length - 2]; |
| p.setDataPosition(0); |
| p.readByteArray(d); |
| for (int i = 0; i < d.length; i++) { |
| Log.d("Trace", "i=" + i + " d[i]=" + d[i]); |
| } |
| for (int i = 0; i < 7; i++) { |
| assertEquals(c[i + 1], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateByteArray() { |
| Parcel p; |
| |
| byte[] a = {(byte) 21}; |
| byte[] b; |
| |
| byte[] c = {Byte.MAX_VALUE, (byte) 111, (byte) 11, (byte) 1, (byte) 0, |
| (byte) -1, (byte) -11, (byte) -111, Byte.MIN_VALUE}; |
| byte[] d; |
| |
| byte[] e = {}; |
| byte[] f; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeByteArray(null); |
| p.setDataPosition(0); |
| b = p.createByteArray(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write byte array with length: 0 |
| p = Parcel.obtain(); |
| p.writeByteArray(e); |
| p.setDataPosition(0); |
| f = p.createByteArray(); |
| assertNotNull(f); |
| assertEquals(0, f.length); |
| p.recycle(); |
| |
| // test write byte array with length: 1 |
| p = Parcel.obtain(); |
| p.writeByteArray(a); |
| p.setDataPosition(0); |
| b = p.createByteArray(); |
| assertNotNull(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write byte array with length: 9 |
| p = Parcel.obtain(); |
| p.writeByteArray(c); |
| p.setDataPosition(0); |
| d = p.createByteArray(); |
| assertNotNull(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadCharArray() { |
| Parcel p; |
| |
| char[] a = {'a'}; |
| char[] b = new char[a.length]; |
| |
| char[] c = {'a', Character.MAX_VALUE, Character.MIN_VALUE, Character.MAX_SURROGATE, Character.MIN_SURROGATE, |
| Character.MAX_HIGH_SURROGATE, Character.MAX_LOW_SURROGATE, |
| Character.MIN_HIGH_SURROGATE, Character.MIN_LOW_SURROGATE}; |
| char[] d = new char[c.length]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeCharArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readCharArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readCharArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write char array with length: 1 |
| p = Parcel.obtain(); |
| p.writeCharArray(a); |
| p.setDataPosition(0); |
| try { |
| p.readCharArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readCharArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write char array with length: 9 |
| p = Parcel.obtain(); |
| p.writeCharArray(c); |
| p.setDataPosition(0); |
| try { |
| p.readCharArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readCharArray(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateCharArray() { |
| Parcel p; |
| |
| char[] a = {'a'}; |
| char[] b; |
| |
| char[] c = {'a', Character.MAX_VALUE, Character.MIN_VALUE, Character.MAX_SURROGATE, Character.MIN_SURROGATE, |
| Character.MAX_HIGH_SURROGATE, Character.MAX_LOW_SURROGATE, |
| Character.MIN_HIGH_SURROGATE, Character.MIN_LOW_SURROGATE}; |
| char[] d; |
| |
| char[] e = {}; |
| char[] f; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeCharArray(null); |
| p.setDataPosition(0); |
| b = p.createCharArray(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write char array with length: 1 |
| p = Parcel.obtain(); |
| p.writeCharArray(e); |
| p.setDataPosition(0); |
| f = p.createCharArray(); |
| assertNotNull(e); |
| assertEquals(0, f.length); |
| p.recycle(); |
| |
| // test write char array with length: 1 |
| p = Parcel.obtain(); |
| p.writeCharArray(a); |
| p.setDataPosition(0); |
| b = p.createCharArray(); |
| assertNotNull(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write char array with length: 9 |
| p = Parcel.obtain(); |
| p.writeCharArray(c); |
| p.setDataPosition(0); |
| d = p.createCharArray(); |
| assertNotNull(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadInt() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| p.writeInt(0); |
| p.setDataPosition(0); |
| assertEquals(0, p.readInt()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInt(1); |
| p.setDataPosition(0); |
| assertEquals(1, p.readInt()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInt(-1); |
| p.setDataPosition(0); |
| assertEquals(-1, p.readInt()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInt(Integer.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Integer.MAX_VALUE, p.readInt()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInt(Integer.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Integer.MIN_VALUE, p.readInt()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInt(Integer.MAX_VALUE); |
| p.writeInt(11); |
| p.writeInt(1); |
| p.writeInt(0); |
| p.writeInt(-1); |
| p.writeInt(-11); |
| p.writeInt(Integer.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Integer.MAX_VALUE, p.readInt()); |
| assertEquals(11, p.readInt()); |
| assertEquals(1, p.readInt()); |
| assertEquals(0, p.readInt()); |
| assertEquals(-1, p.readInt()); |
| assertEquals(-11, p.readInt()); |
| assertEquals(Integer.MIN_VALUE, p.readInt()); |
| p.recycle(); |
| } |
| |
| public void testReadIntArray() { |
| Parcel p; |
| |
| int[] a = {21}; |
| int[] b = new int[a.length]; |
| |
| int[] c = {Integer.MAX_VALUE, 111, 11, 1, 0, -1, -11, -111, Integer.MIN_VALUE}; |
| int[] d = new int[c.length]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeIntArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readIntArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readIntArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write int array with length: 1 |
| p = Parcel.obtain(); |
| p.writeIntArray(a); |
| p.setDataPosition(0); |
| try { |
| p.readIntArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readIntArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write int array with length: 9 |
| p = Parcel.obtain(); |
| p.writeIntArray(c); |
| p.setDataPosition(0); |
| try { |
| p.readIntArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readIntArray(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateIntArray() { |
| Parcel p; |
| |
| int[] a = {21}; |
| int[] b; |
| |
| int[] c = {Integer.MAX_VALUE, 111, 11, 1, 0, -1, -11, -111, Integer.MIN_VALUE}; |
| int[] d; |
| |
| int[] e = {}; |
| int[] f; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeIntArray(null); |
| p.setDataPosition(0); |
| b = p.createIntArray(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write int array with length: 0 |
| p = Parcel.obtain(); |
| p.writeIntArray(e); |
| p.setDataPosition(0); |
| f = p.createIntArray(); |
| assertNotNull(e); |
| assertEquals(0, f.length); |
| p.recycle(); |
| |
| // test write int array with length: 1 |
| p = Parcel.obtain(); |
| p.writeIntArray(a); |
| p.setDataPosition(0); |
| b = p.createIntArray(); |
| assertNotNull(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write int array with length: 9 |
| p = Parcel.obtain(); |
| p.writeIntArray(c); |
| p.setDataPosition(0); |
| d = p.createIntArray(); |
| assertNotNull(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadLong() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| p.writeLong(0L); |
| p.setDataPosition(0); |
| assertEquals(0, p.readLong()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeLong(1L); |
| p.setDataPosition(0); |
| assertEquals(1, p.readLong()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeLong(-1L); |
| p.setDataPosition(0); |
| assertEquals(-1L, p.readLong()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeLong(Long.MAX_VALUE); |
| p.writeLong(11L); |
| p.writeLong(1L); |
| p.writeLong(0L); |
| p.writeLong(-1L); |
| p.writeLong(-11L); |
| p.writeLong(Long.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Long.MAX_VALUE, p.readLong()); |
| assertEquals(11L, p.readLong()); |
| assertEquals(1L, p.readLong()); |
| assertEquals(0L, p.readLong()); |
| assertEquals(-1L, p.readLong()); |
| assertEquals(-11L, p.readLong()); |
| assertEquals(Long.MIN_VALUE, p.readLong()); |
| p.recycle(); |
| } |
| |
| public void testReadLongArray() { |
| Parcel p; |
| |
| long[] a = {21L}; |
| long[] b = new long[a.length]; |
| |
| long[] c = {Long.MAX_VALUE, 111L, 11L, 1L, 0L, -1L, -11L, -111L, Long.MIN_VALUE}; |
| long[] d = new long[c.length]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeLongArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readLongArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readLongArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write long array with length: 1 |
| p = Parcel.obtain(); |
| p.writeLongArray(a); |
| p.setDataPosition(0); |
| try { |
| p.readLongArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readLongArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write long array with length: 9 |
| p = Parcel.obtain(); |
| p.writeLongArray(c); |
| p.setDataPosition(0); |
| try { |
| p.readLongArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readLongArray(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateLongArray() { |
| Parcel p; |
| |
| long[] a = {21L}; |
| long[] b; |
| |
| long[] c = {Long.MAX_VALUE, 111L, 11L, 1L, 0L, -1L, -11L, -111L, Long.MIN_VALUE}; |
| long[] d; |
| |
| long[] e = {}; |
| long[] f; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeLongArray(null); |
| p.setDataPosition(0); |
| b = p.createLongArray(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write long array with length: 0 |
| p = Parcel.obtain(); |
| p.writeLongArray(e); |
| p.setDataPosition(0); |
| f = p.createLongArray(); |
| assertNotNull(e); |
| assertEquals(0, f.length); |
| p.recycle(); |
| |
| // test write long array with length: 1 |
| p = Parcel.obtain(); |
| p.writeLongArray(a); |
| p.setDataPosition(0); |
| b = p.createLongArray(); |
| assertNotNull(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write long array with length: 9 |
| p = Parcel.obtain(); |
| p.writeLongArray(c); |
| p.setDataPosition(0); |
| d = p.createLongArray(); |
| assertNotNull(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadFloat() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| p.writeFloat(.0f); |
| p.setDataPosition(0); |
| assertEquals(.0f, p.readFloat()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeFloat(0.1f); |
| p.setDataPosition(0); |
| assertEquals(0.1f, p.readFloat()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeFloat(-1.1f); |
| p.setDataPosition(0); |
| assertEquals(-1.1f, p.readFloat()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeFloat(Float.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Float.MAX_VALUE, p.readFloat()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeFloat(Float.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Float.MIN_VALUE, p.readFloat()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeFloat(Float.MAX_VALUE); |
| p.writeFloat(1.1f); |
| p.writeFloat(0.1f); |
| p.writeFloat(.0f); |
| p.writeFloat(-0.1f); |
| p.writeFloat(-1.1f); |
| p.writeFloat(Float.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Float.MAX_VALUE, p.readFloat()); |
| assertEquals(1.1f, p.readFloat()); |
| assertEquals(0.1f, p.readFloat()); |
| assertEquals(.0f, p.readFloat()); |
| assertEquals(-0.1f, p.readFloat()); |
| assertEquals(-1.1f, p.readFloat()); |
| assertEquals(Float.MIN_VALUE, p.readFloat()); |
| p.recycle(); |
| } |
| |
| public void testReadFloatArray() { |
| Parcel p; |
| |
| float[] a = {2.1f}; |
| float[] b = new float[a.length]; |
| |
| float[] c = {Float.MAX_VALUE, 11.1f, 1.1f, 0.1f, .0f, -0.1f, -1.1f, -11.1f, Float.MIN_VALUE}; |
| float[] d = new float[c.length]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeFloatArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readFloatArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readFloatArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write float array with length: 1 |
| p = Parcel.obtain(); |
| p.writeFloatArray(a); |
| p.setDataPosition(0); |
| try { |
| p.readFloatArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readFloatArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write float array with length: 9 |
| p = Parcel.obtain(); |
| p.writeFloatArray(c); |
| p.setDataPosition(0); |
| try { |
| p.readFloatArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readFloatArray(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateFloatArray() { |
| Parcel p; |
| |
| float[] a = {2.1f}; |
| float[] b; |
| |
| float[] c = {Float.MAX_VALUE, 11.1f, 1.1f, 0.1f, .0f, -0.1f, -1.1f, -11.1f, Float.MIN_VALUE}; |
| float[] d; |
| |
| float[] e = {}; |
| float[] f; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeFloatArray(null); |
| p.setDataPosition(0); |
| b = p.createFloatArray(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write float array with length: 0 |
| p = Parcel.obtain(); |
| p.writeFloatArray(e); |
| p.setDataPosition(0); |
| f = p.createFloatArray(); |
| assertNotNull(f); |
| assertEquals(0, f.length); |
| p.recycle(); |
| |
| // test write float array with length: 1 |
| p = Parcel.obtain(); |
| p.writeFloatArray(a); |
| p.setDataPosition(0); |
| b = p.createFloatArray(); |
| assertNotNull(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write float array with length: 9 |
| p = Parcel.obtain(); |
| p.writeFloatArray(c); |
| p.setDataPosition(0); |
| d = p.createFloatArray(); |
| assertNotNull(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadDouble() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| p.writeDouble(.0d); |
| p.setDataPosition(0); |
| assertEquals(.0d, p.readDouble()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeDouble(0.1d); |
| p.setDataPosition(0); |
| assertEquals(0.1d, p.readDouble()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeDouble(-1.1d); |
| p.setDataPosition(0); |
| assertEquals(-1.1d, p.readDouble()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeDouble(Double.MAX_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Double.MAX_VALUE, p.readDouble()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeDouble(Double.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Double.MIN_VALUE, p.readDouble()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeDouble(Double.MAX_VALUE); |
| p.writeDouble(1.1d); |
| p.writeDouble(0.1d); |
| p.writeDouble(.0d); |
| p.writeDouble(-0.1d); |
| p.writeDouble(-1.1d); |
| p.writeDouble(Double.MIN_VALUE); |
| p.setDataPosition(0); |
| assertEquals(Double.MAX_VALUE, p.readDouble()); |
| assertEquals(1.1d, p.readDouble()); |
| assertEquals(0.1d, p.readDouble()); |
| assertEquals(.0d, p.readDouble()); |
| assertEquals(-0.1d, p.readDouble()); |
| assertEquals(-1.1d, p.readDouble()); |
| assertEquals(Double.MIN_VALUE, p.readDouble()); |
| p.recycle(); |
| } |
| |
| public void testReadDoubleArray() { |
| Parcel p; |
| |
| double[] a = {2.1d}; |
| double[] b = new double[a.length]; |
| |
| double[] c = {Double.MAX_VALUE, 11.1d, 1.1d, 0.1d, .0d, -0.1d, -1.1d, -11.1d, Double.MIN_VALUE}; |
| double[] d = new double[c.length]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeDoubleArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readDoubleArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readDoubleArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write double array with length: 1 |
| p = Parcel.obtain(); |
| p.writeDoubleArray(a); |
| p.setDataPosition(0); |
| try { |
| p.readDoubleArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readDoubleArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write double array with length: 9 |
| p = Parcel.obtain(); |
| p.writeDoubleArray(c); |
| p.setDataPosition(0); |
| try { |
| p.readDoubleArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readDoubleArray(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateDoubleArray() { |
| Parcel p; |
| |
| double[] a = {2.1d}; |
| double[] b; |
| |
| double[] c = { |
| Double.MAX_VALUE, 11.1d, 1.1d, 0.1d, .0d, -0.1d, -1.1d, -11.1d, Double.MIN_VALUE |
| }; |
| double[] d; |
| |
| double[] e = {}; |
| double[] f; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeDoubleArray(null); |
| p.setDataPosition(0); |
| b = p.createDoubleArray(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write double array with length: 0 |
| p = Parcel.obtain(); |
| p.writeDoubleArray(e); |
| p.setDataPosition(0); |
| f = p.createDoubleArray(); |
| assertNotNull(f); |
| assertEquals(0, f.length); |
| p.recycle(); |
| |
| // test write double array with length: 1 |
| p = Parcel.obtain(); |
| p.writeDoubleArray(a); |
| p.setDataPosition(0); |
| b = p.createDoubleArray(); |
| assertNotNull(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write double array with length: 9 |
| p = Parcel.obtain(); |
| p.writeDoubleArray(c); |
| p.setDataPosition(0); |
| d = p.createDoubleArray(); |
| assertNotNull(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadBooleanArray() { |
| Parcel p; |
| |
| boolean[] a = {true}; |
| boolean[] b = new boolean[a.length]; |
| |
| boolean[] c = {true, false, true, false}; |
| boolean[] d = new boolean[c.length]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeBooleanArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readIntArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readBooleanArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write boolean array with length: 1 |
| p = Parcel.obtain(); |
| p.writeBooleanArray(a); |
| p.setDataPosition(0); |
| try { |
| p.readBooleanArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readBooleanArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write boolean array with length: 4 |
| p = Parcel.obtain(); |
| p.writeBooleanArray(c); |
| p.setDataPosition(0); |
| try { |
| p.readBooleanArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readBooleanArray(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateBooleanArray() { |
| Parcel p; |
| |
| boolean[] a = {true}; |
| boolean[] b; |
| |
| boolean[] c = {true, false, true, false}; |
| boolean[] d; |
| |
| boolean[] e = {}; |
| boolean[] f; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeBooleanArray(null); |
| p.setDataPosition(0); |
| b = p.createBooleanArray(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write boolean array with length: 0 |
| p = Parcel.obtain(); |
| p.writeBooleanArray(e); |
| p.setDataPosition(0); |
| f = p.createBooleanArray(); |
| assertNotNull(f); |
| assertEquals(0, f.length); |
| p.recycle(); |
| |
| // test write boolean array with length: 1 |
| p = Parcel.obtain(); |
| p.writeBooleanArray(a); |
| |
| p.setDataPosition(0); |
| b = p.createBooleanArray(); |
| assertNotNull(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write boolean array with length: 4 |
| p = Parcel.obtain(); |
| p.writeBooleanArray(c); |
| p.setDataPosition(0); |
| d = p.createBooleanArray(); |
| assertNotNull(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadString() { |
| Parcel p; |
| final String string = "Hello, Android!"; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeString(null); |
| p.setDataPosition(0); |
| assertNull(p.readString()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeString(""); |
| p.setDataPosition(0); |
| assertEquals("", p.readString()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeString("a"); |
| p.setDataPosition(0); |
| assertEquals("a", p.readString()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeString(string); |
| p.setDataPosition(0); |
| assertEquals(string, p.readString()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeString(string); |
| p.writeString("a"); |
| p.writeString(""); |
| p.setDataPosition(0); |
| assertEquals(string, p.readString()); |
| assertEquals("a", p.readString()); |
| assertEquals("", p.readString()); |
| p.recycle(); |
| } |
| |
| public void testReadStringArray() { |
| Parcel p; |
| |
| String[] a = {"21"}; |
| String[] b = new String[a.length]; |
| |
| String[] c = {"", |
| "a", |
| "Hello, Android!", |
| "A long string that is used to test the api readStringArray(),"}; |
| String[] d = new String[c.length]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeStringArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readStringArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readStringArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write String array with length: 1 |
| p = Parcel.obtain(); |
| p.writeStringArray(a); |
| p.setDataPosition(0); |
| try { |
| p.readStringArray(d); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readStringArray(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write String array with length: 9 |
| p = Parcel.obtain(); |
| p.writeStringArray(c); |
| p.setDataPosition(0); |
| try { |
| p.readStringArray(b); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readStringArray(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateStringArray() { |
| Parcel p; |
| |
| String[] a = {"21"}; |
| String[] b; |
| |
| String[] c = {"", |
| "a", |
| "Hello, Android!", |
| "A long string that is used to test the api readStringArray(),"}; |
| String[] d; |
| |
| String[] e = {}; |
| String[] f; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeStringArray(null); |
| p.setDataPosition(0); |
| b = p.createStringArray(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write String array with length: 0 |
| p = Parcel.obtain(); |
| p.writeStringArray(e); |
| p.setDataPosition(0); |
| f = p.createStringArray(); |
| assertNotNull(e); |
| assertEquals(0, f.length); |
| p.recycle(); |
| |
| // test write String array with length: 1 |
| p = Parcel.obtain(); |
| p.writeStringArray(a); |
| p.setDataPosition(0); |
| b = p.createStringArray(); |
| assertNotNull(b); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(a[i], b[i]); |
| } |
| p.recycle(); |
| |
| // test write String array with length: 9 |
| p = Parcel.obtain(); |
| p.writeStringArray(c); |
| p.setDataPosition(0); |
| d = p.createStringArray(); |
| assertNotNull(d); |
| for (int i = 0; i < c.length; i++) { |
| assertEquals(c[i], d[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadStringList() { |
| Parcel p; |
| |
| ArrayList<String> a = new ArrayList<String>(); |
| a.add("21"); |
| ArrayList<String> b = new ArrayList<String>(); |
| |
| ArrayList<String> c = new ArrayList<String>(); |
| c.add(""); |
| c.add("a"); |
| c.add("Hello, Android!"); |
| c.add("A long string that is used to test the api readStringList(),"); |
| ArrayList<String> d = new ArrayList<String>(); |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeStringList(null); |
| p.setDataPosition(0); |
| try { |
| p.readStringList(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readStringList(b); |
| assertTrue(0 == b.size()); |
| p.recycle(); |
| |
| // test write String array with length: 1 |
| p = Parcel.obtain(); |
| p.writeStringList(a); |
| p.setDataPosition(0); |
| assertTrue(c.size() > a.size()); |
| p.readStringList(c); |
| assertTrue(c.size() == a.size()); |
| assertEquals(a, c); |
| |
| p.setDataPosition(0); |
| assertTrue(0 == b.size() && 0 != a.size()); |
| p.readStringList(b); |
| assertEquals(a, b); |
| p.recycle(); |
| |
| c = new ArrayList<String>(); |
| c.add(""); |
| c.add("a"); |
| c.add("Hello, Android!"); |
| c.add("A long string that is used to test the api readStringList(),"); |
| // test write String array with length: 4 |
| p = Parcel.obtain(); |
| p.writeStringList(c); |
| p.setDataPosition(0); |
| |
| assertTrue(b.size() < c.size()); |
| p.readStringList(b); |
| assertTrue(b.size() == c.size()); |
| assertEquals(c, b); |
| |
| p.setDataPosition(0); |
| assertTrue(d.size() < c.size()); |
| p.readStringList(d); |
| assertEquals(c, d); |
| p.recycle(); |
| } |
| |
| public void testCreateStringArrayList() { |
| Parcel p; |
| |
| ArrayList<String> a = new ArrayList<String>(); |
| a.add("21"); |
| ArrayList<String> b; |
| |
| ArrayList<String> c = new ArrayList<String>(); |
| c.add(""); |
| c.add("a"); |
| c.add("Hello, Android!"); |
| c.add("A long string that is used to test the api readStringList(),"); |
| ArrayList<String> d; |
| |
| ArrayList<String> e = new ArrayList<String>(); |
| ArrayList<String> f = null; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeStringList(null); |
| p.setDataPosition(0); |
| b = p.createStringArrayList(); |
| assertNull(b); |
| p.recycle(); |
| |
| // test write String array with length: 0 |
| p = Parcel.obtain(); |
| p.writeStringList(e); |
| p.setDataPosition(0); |
| assertNull(f); |
| f = p.createStringArrayList(); |
| assertNotNull(f); |
| p.recycle(); |
| |
| // test write String array with length: 1 |
| p = Parcel.obtain(); |
| p.writeStringList(a); |
| p.setDataPosition(0); |
| b = p.createStringArrayList(); |
| assertEquals(a, b); |
| p.recycle(); |
| |
| // test write String array with length: 4 |
| p = Parcel.obtain(); |
| p.writeStringList(c); |
| p.setDataPosition(0); |
| d = p.createStringArrayList(); |
| assertEquals(c, d); |
| p.recycle(); |
| } |
| |
| public void testReadSerializable() { |
| Parcel p; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeSerializable(null); |
| p.setDataPosition(0); |
| assertNull(p.readSerializable()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeSerializable("Hello, Android!"); |
| p.setDataPosition(0); |
| assertEquals("Hello, Android!", p.readSerializable()); |
| p.recycle(); |
| } |
| |
| public void testReadSerializableWithClass_whenNull(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| p.writeSerializable(null); |
| p.setDataPosition(0); |
| assertNull(p.readSerializable(mcl, Exception.class)); |
| |
| p.setDataPosition(0); |
| assertNull(p.readSerializable(null, Exception.class)); |
| p.recycle(); |
| } |
| |
| public void testReadSerializableWithClass_whenNullClassLoader(){ |
| Parcel p = Parcel.obtain(); |
| TestSubException testSubException = new TestSubException("test"); |
| p.writeSerializable(testSubException); |
| p.setDataPosition(0); |
| Throwable error = assertThrows(BadParcelableException.class, () -> |
| p.readSerializable(null, TestSubException.class)); |
| assertTrue(error.getMessage().contains("ClassNotFoundException reading a Serializable")); |
| p.recycle(); |
| } |
| |
| public void testReadSerializableWithClass_whenSameClass(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| Throwable throwable = new Throwable("test"); |
| p.writeSerializable(throwable); |
| p.setDataPosition(0); |
| Object object = p.readSerializable(mcl, Throwable.class); |
| assertTrue(object instanceof Throwable); |
| Throwable t1 = (Throwable) object; |
| assertEquals("test", t1.getMessage()); |
| |
| p.setDataPosition(0); |
| Object object1 = p.readSerializable(null, Throwable.class); |
| assertTrue(object1 instanceof Throwable); |
| Throwable t2 = (Throwable) object1; |
| assertEquals("test", t2.getMessage()); |
| p.recycle(); |
| } |
| |
| public void testReadSerializableWithClass_whenSubClass(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| Exception exception = new Exception("test"); |
| p.writeSerializable(exception); |
| p.setDataPosition(0); |
| Object object = p.readSerializable(mcl, Throwable.class); |
| assertTrue(object instanceof Exception); |
| Exception e1 = (Exception) object; |
| assertEquals("test", e1.getMessage()); |
| |
| p.setDataPosition(0); |
| Object object1 = p.readSerializable(null, Throwable.class); |
| assertTrue(object1 instanceof Exception); |
| Exception e2 = (Exception) object1; |
| assertEquals("test", e2.getMessage()); |
| |
| p.setDataPosition(0); |
| Object object2 = p.readSerializable(null, Object.class); |
| assertTrue(object1 instanceof Exception); |
| Exception e3 = (Exception) object2; |
| assertEquals("test", e3.getMessage()); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readSerializable(mcl, String.class)); |
| p.recycle(); |
| } |
| |
| public void testReadParcelable() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| final String signatureString = "1234567890abcdef"; |
| Signature s = new Signature(signatureString); |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeParcelable(null, 0); |
| p.setDataPosition(0); |
| assertNull(p.readParcelable(mcl)); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeParcelable(s, 0); |
| p.setDataPosition(0); |
| assertEquals(s, p.readParcelable(mcl)); |
| |
| p.recycle(); |
| } |
| |
| public void testReadParcelableWithClass() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| final String signatureString = "1234567890abcdef"; |
| Signature s = new Signature(signatureString); |
| |
| p = Parcel.obtain(); |
| p.writeParcelable(s, 0); |
| p.setDataPosition(0); |
| assertEquals(s, p.readParcelable(mcl, Signature.class)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readParcelable(mcl, Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadParcelableWithSubClass() { |
| Parcel p; |
| |
| final TestSubIntent testSubIntent = new TestSubIntent(new Intent(), "Test"); |
| p = Parcel.obtain(); |
| p.writeParcelable(testSubIntent, 0); |
| p.setDataPosition(0); |
| assertEquals(testSubIntent, (p.readParcelable(getClass().getClassLoader(), Intent.class))); |
| |
| p.setDataPosition(0); |
| assertEquals(testSubIntent, (p.readParcelable(getClass().getClassLoader(), Object.class))); |
| p.recycle(); |
| } |
| |
| public void testReadParcelableCreator() { |
| MockClassLoader mcl = new MockClassLoader(); |
| final String signatureString = "1234567890abcdef"; |
| Signature s = new Signature(signatureString); |
| |
| Parcel p = Parcel.obtain(); |
| p.writeParcelableCreator(s); |
| p.setDataPosition(0); |
| assertSame(Signature.CREATOR, p.readParcelableCreator(mcl)); |
| |
| p.recycle(); |
| } |
| |
| public void testReadParcelableCreatorWithClass() { |
| MockClassLoader mcl = new MockClassLoader(); |
| final String signatureString = "1234567890abcdef"; |
| Signature s = new Signature(signatureString); |
| |
| Parcel p = Parcel.obtain(); |
| p.writeParcelableCreator(s); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readParcelableCreator(mcl, Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadParcelableCreatorWithSubClass() { |
| final TestSubIntent testSubIntent = new TestSubIntent(new Intent(), "1234567890abcdef"); |
| |
| Parcel p = Parcel.obtain(); |
| p.writeParcelableCreator(testSubIntent); |
| |
| p.setDataPosition(0); |
| assertSame(TestSubIntent.CREATOR, |
| p.readParcelableCreator(getClass().getClassLoader(), Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadParcelableArray() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| Signature[] s = {new Signature("1234"), |
| new Signature("ABCD"), |
| new Signature("abcd")}; |
| |
| Signature[] s2 = {new Signature("1234"), |
| null, |
| new Signature("abcd")}; |
| Parcelable[] s3; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeParcelableArray(null, 0); |
| p.setDataPosition(0); |
| assertNull(p.readParcelableArray(mcl)); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeParcelableArray(s, 0); |
| p.setDataPosition(0); |
| s3 = p.readParcelableArray(mcl); |
| for (int i = 0; i < s.length; i++) { |
| assertEquals(s[i], s3[i]); |
| } |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeParcelableArray(s2, 0); |
| p.setDataPosition(0); |
| s3 = p.readParcelableArray(mcl); |
| for (int i = 0; i < s2.length; i++) { |
| assertEquals(s2[i], s3[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadParcelableArrayWithClass_whenNull() { |
| Parcel p = Parcel.obtain(); |
| p.writeParcelableArray(null, 0); |
| p.setDataPosition(0); |
| assertNull(p.readParcelableArray(getClass().getClassLoader(), Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadParcelableArrayWithClass_whenSameClass(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| Signature[] s = {new Signature("1234"), |
| null, |
| new Signature("abcd") |
| }; |
| p.writeParcelableArray(s, 0); |
| p.setDataPosition(0); |
| Parcelable[] s1 = p.readParcelableArray(mcl, Signature.class); |
| assertTrue(Arrays.equals(s, s1)); |
| p.recycle(); |
| } |
| |
| public void testReadParcelableArrayWithClass_whenSubclasses() { |
| Parcel p = Parcel.obtain(); |
| final Intent baseIntent = new Intent(); |
| Intent[] intentArray = { |
| new TestSubIntent(baseIntent, "1234567890abcdef"), |
| null, |
| new TestSubIntent(baseIntent, "abcdef1234567890") |
| }; |
| |
| p.writeParcelableArray(intentArray, 0); |
| p.setDataPosition(0); |
| Parcelable[] s = p.readParcelableArray(getClass().getClassLoader(), Intent.class); |
| assertTrue(Arrays.equals(intentArray, s)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readParcelableArray( |
| getClass().getClassLoader(), Signature.class)); |
| p.recycle(); |
| } |
| |
| public void testReadTypedArray() { |
| Parcel p; |
| Signature[] s = {new Signature("1234"), |
| new Signature("ABCD"), |
| new Signature("abcd")}; |
| |
| Signature[] s2 = {new Signature("1234"), |
| null, |
| new Signature("abcd")}; |
| Signature[] s3 = new Signature[3]; |
| Signature[] s4 = new Signature[4]; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeTypedArray(null, 0); |
| p.setDataPosition(0); |
| try { |
| p.readTypedArray(s3, Signature.CREATOR); |
| fail("should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readTypedArray(null, Signature.CREATOR); |
| fail("should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write not null |
| p = Parcel.obtain(); |
| p.writeTypedArray(s, 0); |
| p.setDataPosition(0); |
| p.readTypedArray(s3, Signature.CREATOR); |
| for (int i = 0; i < s.length; i++) { |
| assertEquals(s[i], s3[i]); |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readTypedArray(null, Signature.CREATOR); |
| fail("should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readTypedArray(s4, Signature.CREATOR); |
| fail("should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| s3 = new Signature[s2.length]; |
| p = Parcel.obtain(); |
| p.writeTypedArray(s2, 0); |
| p.setDataPosition(0); |
| p.readTypedArray(s3, Signature.CREATOR); |
| for (int i = 0; i < s.length; i++) { |
| assertEquals(s2[i], s3[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadTypedArray2() { |
| Parcel p; |
| Signature[] s = { |
| new Signature("1234"), new Signature("ABCD"), new Signature("abcd") |
| }; |
| |
| Signature[] s2 = { |
| new Signature("1234"), null, new Signature("abcd") |
| }; |
| Signature[] s3 = { |
| null, null, null |
| }; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeTypedArray(null, 0); |
| p.setDataPosition(0); |
| p.recycle(); |
| |
| // test write not null |
| p = Parcel.obtain(); |
| p.writeTypedArray(s, 0); |
| p.setDataPosition(0); |
| p.readTypedArray(s3, Signature.CREATOR); |
| for (int i = 0; i < s.length; i++) { |
| assertEquals(s[i], s3[i]); |
| } |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeTypedArray(s2, 0); |
| p.setDataPosition(0); |
| p.readTypedArray(s3, Signature.CREATOR); |
| for (int i = 0; i < s.length; i++) { |
| assertEquals(s2[i], s3[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateTypedArray() { |
| Parcel p; |
| Signature[] s = {new Signature("1234"), |
| new Signature("ABCD"), |
| new Signature("abcd")}; |
| |
| Signature[] s2 = {new Signature("1234"), |
| null, |
| new Signature("abcd")}; |
| Signature[] s3; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeTypedArray(null, 0); |
| p.setDataPosition(0); |
| assertNull(p.createTypedArray(Signature.CREATOR)); |
| p.recycle(); |
| |
| // test write not null |
| p = Parcel.obtain(); |
| p.writeTypedArray(s, 0); |
| p.setDataPosition(0); |
| s3 = p.createTypedArray(Signature.CREATOR); |
| for (int i = 0; i < s.length; i++) { |
| assertEquals(s[i], s3[i]); |
| } |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeTypedArray(s2, 0); |
| p.setDataPosition(0); |
| s3 = p.createTypedArray(Signature.CREATOR); |
| for (int i = 0; i < s.length; i++) { |
| assertEquals(s2[i], s3[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadTypedList() { |
| Parcel p; |
| ArrayList<Signature> s = new ArrayList<Signature>(); |
| s.add(new Signature("1234")); |
| s.add(new Signature("ABCD")); |
| s.add(new Signature("abcd")); |
| |
| ArrayList<Signature> s2 = new ArrayList<Signature>(); |
| s2.add(new Signature("1234")); |
| s2.add(null); |
| |
| ArrayList<Signature> s3 = new ArrayList<Signature>(); |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeTypedList(null); |
| p.setDataPosition(0); |
| p.readTypedList(s3, Signature.CREATOR); |
| assertEquals(0, s3.size()); |
| |
| p.setDataPosition(0); |
| try { |
| p.readTypedList(null, Signature.CREATOR); |
| fail("should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| // test write not null |
| p = Parcel.obtain(); |
| p.writeTypedList(s); |
| p.setDataPosition(0); |
| p.readTypedList(s3, Signature.CREATOR); |
| for (int i = 0; i < s.size(); i++) { |
| assertEquals(s.get(i), s3.get(i)); |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readTypedList(null, Signature.CREATOR); |
| fail("should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readTypedList(s2, Signature.CREATOR); |
| assertEquals(s.size(), s2.size()); |
| for (int i = 0; i < s.size(); i++) { |
| assertEquals(s.get(i), s2.get(i)); |
| } |
| p.recycle(); |
| |
| s2 = new ArrayList<Signature>(); |
| s2.add(new Signature("1234")); |
| s2.add(null); |
| p = Parcel.obtain(); |
| p.writeTypedList(s2); |
| p.setDataPosition(0); |
| p.readTypedList(s3, Signature.CREATOR); |
| assertEquals(s3.size(), s2.size()); |
| for (int i = 0; i < s2.size(); i++) { |
| assertEquals(s2.get(i), s3.get(i)); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateTypedArrayList() { |
| Parcel p; |
| ArrayList<Signature> s = new ArrayList<Signature>(); |
| s.add(new Signature("1234")); |
| s.add(new Signature("ABCD")); |
| s.add(new Signature("abcd")); |
| |
| ArrayList<Signature> s2 = new ArrayList<Signature>(); |
| s2.add(new Signature("1234")); |
| s2.add(null); |
| |
| ArrayList<Signature> s3; |
| |
| // test write null |
| p = Parcel.obtain(); |
| p.writeTypedList(null); |
| p.setDataPosition(0); |
| assertNull(p.createTypedArrayList(Signature.CREATOR)); |
| p.recycle(); |
| |
| // test write not null |
| p = Parcel.obtain(); |
| p.writeTypedList(s); |
| p.setDataPosition(0); |
| s3 = p.createTypedArrayList(Signature.CREATOR); |
| for (int i = 0; i < s.size(); i++) { |
| assertEquals(s.get(i), s3.get(i)); |
| } |
| |
| p = Parcel.obtain(); |
| p.writeTypedList(s2); |
| p.setDataPosition(0); |
| s3 = p.createTypedArrayList(Signature.CREATOR); |
| assertEquals(s3.size(), s2.size()); |
| for (int i = 0; i < s2.size(); i++) { |
| assertEquals(s2.get(i), s3.get(i)); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadException() { |
| } |
| |
| public void testReadException2() { |
| Parcel p = Parcel.obtain(); |
| String msg = "testReadException2"; |
| |
| p.writeException(new SecurityException(msg)); |
| p.setDataPosition(0); |
| try { |
| p.readException(); |
| fail("Should throw a SecurityException"); |
| } catch (SecurityException e) { |
| assertEquals(msg, e.getMessage()); |
| } |
| |
| p.setDataPosition(0); |
| p.writeException(new BadParcelableException(msg)); |
| p.setDataPosition(0); |
| try { |
| p.readException(); |
| fail("Should throw a BadParcelableException"); |
| } catch (BadParcelableException e) { |
| assertEquals(msg, e.getMessage()); |
| } |
| |
| p.setDataPosition(0); |
| p.writeException(new IllegalArgumentException(msg)); |
| p.setDataPosition(0); |
| try { |
| p.readException(); |
| fail("Should throw an IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| assertEquals(msg, e.getMessage()); |
| } |
| |
| p.setDataPosition(0); |
| p.writeException(new NullPointerException(msg)); |
| p.setDataPosition(0); |
| try { |
| p.readException(); |
| fail("Should throw a NullPointerException"); |
| } catch (NullPointerException e) { |
| assertEquals(msg, e.getMessage()); |
| } |
| |
| p.setDataPosition(0); |
| p.writeException(new IllegalStateException(msg)); |
| p.setDataPosition(0); |
| try { |
| p.readException(); |
| fail("Should throw an IllegalStateException"); |
| } catch (IllegalStateException e) { |
| assertEquals(msg, e.getMessage()); |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.writeException(new RuntimeException()); |
| fail("Should throw an IllegalStateException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| } |
| |
| public void testWriteNoException() { |
| Parcel p = Parcel.obtain(); |
| p.writeNoException(); |
| p.setDataPosition(0); |
| p.readException(); |
| p.recycle(); |
| } |
| |
| public void testWriteFileDescriptor() { |
| Parcel p; |
| FileDescriptor fIn = FileDescriptor.in; |
| ParcelFileDescriptor pfd; |
| |
| p = Parcel.obtain(); |
| pfd = p.readFileDescriptor(); |
| assertNull(pfd); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeFileDescriptor(fIn); |
| p.setDataPosition(0); |
| pfd = p.readFileDescriptor(); |
| assertNotNull(pfd); |
| assertNotNull(pfd.getFileDescriptor()); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptor() { |
| Parcel p; |
| FileDescriptor fIn = FileDescriptor.in; |
| |
| p = Parcel.obtain(); |
| p.writeFileDescriptor(fIn); |
| p.setDataPosition(0); |
| assertTrue(p.hasFileDescriptors()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInt(111); |
| p.setDataPosition(0); |
| assertFalse(p.hasFileDescriptors()); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_outsideRange() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeInt(13); |
| int i1 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| int i2 = p.dataPosition(); |
| p.writeString("Tiramisu"); |
| int i3 = p.dataPosition(); |
| |
| assertFalse(p.hasFileDescriptors(i0, i1 - i0)); |
| assertFalse(p.hasFileDescriptors(i2, i3 - i2)); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_partiallyInsideRange() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeInt(13); |
| int i1 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| int i2 = p.dataPosition(); |
| p.writeString("Tiramisu"); |
| int i3 = p.dataPosition(); |
| |
| // It has to contain the whole object |
| assertFalse(p.hasFileDescriptors(i1, i2 - i1 - 1)); |
| assertFalse(p.hasFileDescriptors(i1 + 1, i2 - i1)); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_insideRange() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeInt(13); |
| int i1 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| int i2 = p.dataPosition(); |
| p.writeString("Tiramisu"); |
| int i3 = p.dataPosition(); |
| |
| assertTrue(p.hasFileDescriptors(i0, i2 - i0)); |
| assertTrue(p.hasFileDescriptors(i1, i2 - i1)); |
| assertTrue(p.hasFileDescriptors(i1, i3 - i1)); |
| assertTrue(p.hasFileDescriptors(i0, i3 - i0)); |
| assertTrue(p.hasFileDescriptors(i0, p.dataSize())); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_zeroLength() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeInt(13); |
| int i1 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| int i2 = p.dataPosition(); |
| p.writeString("Tiramisu"); |
| int i3 = p.dataPosition(); |
| |
| assertFalse(p.hasFileDescriptors(i1, 0)); |
| p.recycle(); |
| } |
| |
| /** |
| * When we rewind the cursor using {@link Parcel#setDataPosition(int)} and write a FD, the |
| * internal representation of FDs in {@link Parcel} may lose the sorted property, so we test |
| * this case. |
| */ |
| public void testHasFileDescriptorInRange_withUnsortedFdObjects() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeLongArray(new long[] {0, 0, 0, 0, 0, 0}); |
| int i1 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| p.setDataPosition(0); |
| p.writeFileDescriptor(FileDescriptor.in); |
| p.setDataPosition(0); |
| |
| assertTrue(p.hasFileDescriptors(i0, i1 - i0)); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_limitOutOfBounds() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| int i1 = p.dataPosition(); |
| |
| assertThrows(IllegalArgumentException.class, () -> p.hasFileDescriptors(i0, i1 - i0 + 1)); |
| assertThrows(IllegalArgumentException.class, |
| () -> p.hasFileDescriptors(0, p.dataSize() + 1)); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_offsetOutOfBounds() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| int i1 = p.dataPosition(); |
| |
| assertThrows(IllegalArgumentException.class, () -> p.hasFileDescriptors(i1, 1)); |
| assertThrows(IllegalArgumentException.class, () -> p.hasFileDescriptors(i1 + 1, 1)); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_offsetOutOfBoundsAndZeroLength() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| int i1 = p.dataPosition(); |
| |
| assertFalse(p.hasFileDescriptors(i1, 0)); |
| assertThrows(IllegalArgumentException.class, () -> p.hasFileDescriptors(i1 + 1, 0)); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_zeroLengthParcel() { |
| Parcel p = Parcel.obtain(); |
| |
| assertFalse(p.hasFileDescriptors(0, 0)); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_negativeLength() { |
| Parcel p = Parcel.obtain(); |
| int i0 = p.dataPosition(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| int i1 = p.dataPosition(); |
| |
| assertThrows(IllegalArgumentException.class, () -> p.hasFileDescriptors(i0, -1)); |
| assertThrows(IllegalArgumentException.class, () -> p.hasFileDescriptors(i0, -(i1 - i0))); |
| p.recycle(); |
| } |
| |
| public void testHasFileDescriptorInRange_negativeOffset() { |
| Parcel p = Parcel.obtain(); |
| p.writeFileDescriptor(FileDescriptor.in); |
| |
| assertThrows(IllegalArgumentException.class, () -> p.hasFileDescriptors(-1, 1)); |
| p.recycle(); |
| } |
| |
| public void testReadBundle() { |
| Bundle bundle = new Bundle(); |
| bundle.putBoolean("boolean", true); |
| bundle.putInt("int", Integer.MAX_VALUE); |
| bundle.putString("string", "String"); |
| |
| Bundle bundle2; |
| Parcel p; |
| |
| // test null |
| p = Parcel.obtain(); |
| p.writeBundle(null); |
| p.setDataPosition(0); |
| bundle2 = p.readBundle(); |
| assertNull(bundle2); |
| p.recycle(); |
| |
| // test not null |
| bundle2 = null; |
| p = Parcel.obtain(); |
| p.writeBundle(bundle); |
| p.setDataPosition(0); |
| bundle2 = p.readBundle(); |
| assertNotNull(bundle2); |
| assertEquals(true, bundle2.getBoolean("boolean")); |
| assertEquals(Integer.MAX_VALUE, bundle2.getInt("int")); |
| assertEquals("String", bundle2.getString("string")); |
| p.recycle(); |
| |
| bundle2 = null; |
| Parcel a = Parcel.obtain(); |
| bundle2 = new Bundle(); |
| bundle2.putString("foo", "test"); |
| a.writeBundle(bundle2); |
| a.setDataPosition(0); |
| bundle.readFromParcel(a); |
| p = Parcel.obtain(); |
| p.setDataPosition(0); |
| p.writeBundle(bundle); |
| p.setDataPosition(0); |
| bundle2 = p.readBundle(); |
| assertNotNull(bundle2); |
| assertFalse(true == bundle2.getBoolean("boolean")); |
| assertFalse(Integer.MAX_VALUE == bundle2.getInt("int")); |
| assertFalse("String".equals( bundle2.getString("string"))); |
| a.recycle(); |
| p.recycle(); |
| } |
| |
| public void testReadBundle2() { |
| Bundle b = new Bundle(); |
| b.putBoolean("boolean", true); |
| b.putInt("int", Integer.MAX_VALUE); |
| b.putString("string", "String"); |
| |
| Bundle u; |
| Parcel p; |
| MockClassLoader m = new MockClassLoader(); |
| |
| p = Parcel.obtain(); |
| p.writeBundle(null); |
| p.setDataPosition(0); |
| u = p.readBundle(m); |
| assertNull(u); |
| p.recycle(); |
| |
| u = null; |
| p = Parcel.obtain(); |
| p.writeBundle(b); |
| p.setDataPosition(0); |
| u = p.readBundle(m); |
| assertNotNull(u); |
| assertEquals(true, b.getBoolean("boolean")); |
| assertEquals(Integer.MAX_VALUE, b.getInt("int")); |
| assertEquals("String", b.getString("string")); |
| p.recycle(); |
| } |
| |
| public void testWriteArray() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| p = Parcel.obtain(); |
| p.writeArray(null); |
| p.setDataPosition(0); |
| assertNull(p.readArray(mcl)); |
| p.recycle(); |
| |
| Object[] objects = new Object[5]; |
| objects[0] = Integer.MAX_VALUE; |
| objects[1] = true; |
| objects[2] = Long.MAX_VALUE; |
| objects[3] = "String"; |
| objects[4] = Float.MAX_VALUE; |
| Object[] objects2; |
| |
| p = Parcel.obtain(); |
| p.writeArray(objects); |
| p.setDataPosition(0); |
| objects2 = p.readArray(mcl); |
| assertNotNull(objects2); |
| for (int i = 0; i < objects2.length; i++) { |
| assertEquals(objects[i], objects2[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadArrayWithClass_whenNull(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| p.writeArray(null); |
| p.setDataPosition(0); |
| assertNull(p.readArray(mcl, Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadArrayWithClass_whenNonParcelableClass(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| String[] sArray = {"1234", null, "4321"}; |
| p.writeArray(sArray); |
| |
| p.setDataPosition(0); |
| Object[] objects = p.readArray(mcl, String.class); |
| assertTrue(Arrays.equals(sArray, objects)); |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readArray( |
| getClass().getClassLoader(), Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadArrayWithClass_whenSameClass(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| Signature[] s = {new Signature("1234"), |
| null, |
| new Signature("abcd")}; |
| p.writeArray(s); |
| |
| p.setDataPosition(0); |
| Object[] s1 = p.readArray(mcl, Signature.class); |
| assertTrue(Arrays.equals(s, s1)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readArray( |
| getClass().getClassLoader(), Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadArrayWithClass_whenSubclasses(){ |
| final Parcel p = Parcel.obtain(); |
| final Intent baseIntent = new Intent(); |
| Intent[] intentArray = { |
| new TestSubIntent(baseIntent, "1234567890abcdef"), |
| null, |
| new TestSubIntent(baseIntent, "abcdef1234567890") |
| }; |
| p.writeArray(intentArray); |
| |
| p.setDataPosition(0); |
| Object[] objects = p.readArray(getClass().getClassLoader(), Intent.class); |
| assertTrue(Arrays.equals(intentArray, objects)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readArray( |
| getClass().getClassLoader(), Signature.class)); |
| p.recycle(); |
| } |
| |
| public void testReadArrayList() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| p = Parcel.obtain(); |
| p.writeArray(null); |
| p.setDataPosition(0); |
| assertNull(p.readArrayList(mcl)); |
| p.recycle(); |
| |
| Object[] objects = new Object[5]; |
| objects[0] = Integer.MAX_VALUE; |
| objects[1] = true; |
| objects[2] = Long.MAX_VALUE; |
| objects[3] = "String"; |
| objects[4] = Float.MAX_VALUE; |
| ArrayList<?> objects2; |
| |
| p = Parcel.obtain(); |
| p.writeArray(objects); |
| p.setDataPosition(0); |
| objects2 = p.readArrayList(mcl); |
| assertNotNull(objects2); |
| for (int i = 0; i < objects2.size(); i++) { |
| assertEquals(objects[i], objects2.get(i)); |
| } |
| p.recycle(); |
| } |
| |
| public void testReadArrayListWithClass_whenNull(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| p.writeArray(null); |
| p.setDataPosition(0); |
| assertNull(p.readArrayList(mcl, Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadArrayListWithClass_whenNonParcelableClass(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| ArrayList<String> sArrayList = new ArrayList<>(); |
| sArrayList.add("1234"); |
| sArrayList.add(null); |
| sArrayList.add("4321"); |
| |
| p.writeList(sArrayList); |
| p.setDataPosition(0); |
| ArrayList<String> s1 = p.readArrayList(mcl, String.class); |
| assertEquals(sArrayList, s1); |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readArray(mcl, Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadArrayListWithClass_whenSameClass(){ |
| final Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| ArrayList<Signature> s = new ArrayList<>(); |
| s.add(new Signature("1234567890abcdef")); |
| s.add(null); |
| s.add(new Signature("abcdef1234567890")); |
| |
| p.writeList(s); |
| p.setDataPosition(0); |
| ArrayList<Signature> s1 = p.readArrayList(mcl, Signature.class); |
| assertEquals(s, s1); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readArray(mcl, Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadArrayListWithClass_whenSubclasses(){ |
| final Parcel p = Parcel.obtain(); |
| final Intent baseIntent = new Intent(); |
| |
| ArrayList<Intent> intentArrayList = new ArrayList<>(); |
| intentArrayList.add(new TestSubIntent(baseIntent, "1234567890abcdef")); |
| intentArrayList.add(null); |
| intentArrayList.add(new TestSubIntent(baseIntent, "abcdef1234567890")); |
| |
| p.writeList(intentArrayList); |
| p.setDataPosition(0); |
| ArrayList<Intent> objects = p.readArrayList(getClass().getClassLoader(), Intent.class); |
| assertEquals(intentArrayList, objects); |
| |
| p.setDataPosition(0); |
| ArrayList<Intent> objects1 = p.readArrayList( |
| getClass().getClassLoader(), TestSubIntent.class); |
| assertEquals(intentArrayList, objects1); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readArray( |
| getClass().getClassLoader(), Signature.class)); |
| p.recycle(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testWriteSparseArray() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| p = Parcel.obtain(); |
| p.writeSparseArray(null); |
| p.setDataPosition(0); |
| assertNull(p.readSparseArray(mcl)); |
| p.recycle(); |
| |
| SparseArray<Object> sparseArray = new SparseArray<Object>(); |
| sparseArray.put(3, "String"); |
| sparseArray.put(2, Long.MAX_VALUE); |
| sparseArray.put(4, Float.MAX_VALUE); |
| sparseArray.put(0, Integer.MAX_VALUE); |
| sparseArray.put(1, true); |
| sparseArray.put(10, true); |
| SparseArray<Object> sparseArray2; |
| |
| p = Parcel.obtain(); |
| p.writeSparseArray(sparseArray); |
| p.setDataPosition(0); |
| sparseArray2 = p.readSparseArray(mcl); |
| assertNotNull(sparseArray2); |
| assertEquals(sparseArray.size(), sparseArray2.size()); |
| assertEquals(sparseArray.get(0), sparseArray2.get(0)); |
| assertEquals(sparseArray.get(1), sparseArray2.get(1)); |
| assertEquals(sparseArray.get(2), sparseArray2.get(2)); |
| assertEquals(sparseArray.get(3), sparseArray2.get(3)); |
| assertEquals(sparseArray.get(4), sparseArray2.get(4)); |
| assertEquals(sparseArray.get(10), sparseArray2.get(10)); |
| p.recycle(); |
| } |
| |
| public void testReadSparseArrayWithClass_whenNull(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| p.writeSparseArray(null); |
| p.setDataPosition(0); |
| assertNull(p.readSparseArray(mcl, Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadSparseArrayWithClass_whenNonParcelableClass(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| SparseArray<String> s = new SparseArray<>(); |
| s.put(0, "1234567890abcdef"); |
| s.put(2, null); |
| s.put(3, "abcdef1234567890"); |
| p.writeSparseArray(s); |
| |
| p.setDataPosition(0); |
| SparseArray<String> s1 = p.readSparseArray(mcl, String.class); |
| assertNotNull(s1); |
| assertTrue(s.contentEquals(s1)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readSparseArray( |
| getClass().getClassLoader(), Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadSparseArrayWithClass_whenSameClass(){ |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| |
| SparseArray<Signature> s = new SparseArray<>(); |
| s.put(0, new Signature("1234567890abcdef")); |
| s.put(2, null); |
| s.put(3, new Signature("abcdef1234567890")); |
| p.writeSparseArray(s); |
| |
| p.setDataPosition(0); |
| SparseArray<Signature> s1 = p.readSparseArray(mcl, Signature.class); |
| assertNotNull(s1); |
| assertTrue(s.contentEquals(s1)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readSparseArray( |
| getClass().getClassLoader(), Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadSparseArrayWithClass_whenSubclasses(){ |
| final Parcel p = Parcel.obtain(); |
| final Intent baseIntent = new Intent(); |
| SparseArray<Intent> intentArray = new SparseArray<>(); |
| intentArray.put(0, new TestSubIntent(baseIntent, "1234567890abcdef")); |
| intentArray.put(3, new TestSubIntent(baseIntent, "1234567890abcdef")); |
| p.writeSparseArray(intentArray); |
| |
| p.setDataPosition(0); |
| SparseArray<Intent> sparseArray = p.readSparseArray( |
| getClass().getClassLoader(), Intent.class); |
| assertNotNull(sparseArray); |
| assertTrue(intentArray.contentEquals(sparseArray)); |
| |
| p.setDataPosition(0); |
| SparseArray<Intent> sparseArray1 = p.readSparseArray( |
| getClass().getClassLoader(), TestSubIntent.class); |
| assertNotNull(sparseArray1); |
| assertTrue(intentArray.contentEquals(sparseArray1)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readSparseArray( |
| getClass().getClassLoader(), Signature.class)); |
| p.recycle(); |
| } |
| |
| public void testWriteSparseBooleanArray() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| p.writeSparseArray(null); |
| p.setDataPosition(0); |
| assertNull(p.readSparseBooleanArray()); |
| p.recycle(); |
| |
| SparseBooleanArray sparseBooleanArray = new SparseBooleanArray(); |
| sparseBooleanArray.put(3, true); |
| sparseBooleanArray.put(2, false); |
| sparseBooleanArray.put(4, false); |
| sparseBooleanArray.put(0, true); |
| sparseBooleanArray.put(1, true); |
| sparseBooleanArray.put(10, true); |
| SparseBooleanArray sparseBoolanArray2; |
| |
| p = Parcel.obtain(); |
| p.writeSparseBooleanArray(sparseBooleanArray); |
| p.setDataPosition(0); |
| sparseBoolanArray2 = p.readSparseBooleanArray(); |
| assertNotNull(sparseBoolanArray2); |
| assertEquals(sparseBooleanArray.size(), sparseBoolanArray2.size()); |
| assertEquals(sparseBooleanArray.get(0), sparseBoolanArray2.get(0)); |
| assertEquals(sparseBooleanArray.get(1), sparseBoolanArray2.get(1)); |
| assertEquals(sparseBooleanArray.get(2), sparseBoolanArray2.get(2)); |
| assertEquals(sparseBooleanArray.get(3), sparseBoolanArray2.get(3)); |
| assertEquals(sparseBooleanArray.get(4), sparseBoolanArray2.get(4)); |
| assertEquals(sparseBooleanArray.get(10), sparseBoolanArray2.get(10)); |
| p.recycle(); |
| } |
| |
| public void testWriteStrongBinder() { |
| Parcel p; |
| Binder binder; |
| Binder binder2 = new Binder(); |
| |
| p = Parcel.obtain(); |
| p.writeStrongBinder(null); |
| p.setDataPosition(0); |
| assertNull(p.readStrongBinder()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeStrongBinder(binder2); |
| p.setDataPosition(0); |
| binder = (Binder) p.readStrongBinder(); |
| assertEquals(binder2, binder); |
| p.recycle(); |
| } |
| |
| public void testWriteStrongInterface() { |
| Parcel p; |
| MockIInterface mockInterface = new MockIInterface(); |
| MockIInterface mockIInterface2 = new MockIInterface(); |
| |
| p = Parcel.obtain(); |
| p.writeStrongInterface(null); |
| p.setDataPosition(0); |
| assertNull(p.readStrongBinder()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeStrongInterface(mockInterface); |
| p.setDataPosition(0); |
| mockIInterface2.binder = (Binder) p.readStrongBinder(); |
| assertEquals(mockInterface.binder, mockIInterface2.binder); |
| p.recycle(); |
| } |
| |
| public void testWriteBinderArray() { |
| Parcel p; |
| IBinder[] ibinder2 = {new Binder(), new Binder()}; |
| IBinder[] ibinder3 = new IBinder[2]; |
| IBinder[] ibinder4 = new IBinder[3]; |
| |
| p = Parcel.obtain(); |
| p.writeBinderArray(null); |
| p.setDataPosition(0); |
| try { |
| p.readBinderArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readBinderArray(ibinder3); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readBinderArray(ibinder2); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeBinderArray(ibinder2); |
| p.setDataPosition(0); |
| try { |
| p.readBinderArray(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| p.readBinderArray(ibinder4); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| p.readBinderArray(ibinder3); |
| assertNotNull(ibinder3); |
| for (int i = 0; i < ibinder3.length; i++) { |
| assertNotNull(ibinder3[i]); |
| assertEquals(ibinder2[i], ibinder3[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testCreateBinderArray() { |
| Parcel p; |
| IBinder[] ibinder = {}; |
| IBinder[] ibinder2 = {new Binder(), new Binder()}; |
| IBinder[] ibinder3; |
| IBinder[] ibinder4; |
| |
| p = Parcel.obtain(); |
| p.writeBinderArray(null); |
| p.setDataPosition(0); |
| ibinder3 = p.createBinderArray(); |
| assertNull(ibinder3); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeBinderArray(ibinder); |
| p.setDataPosition(0); |
| ibinder4 = p.createBinderArray(); |
| assertNotNull(ibinder4); |
| assertEquals(0, ibinder4.length); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeBinderArray(ibinder2); |
| p.setDataPosition(0); |
| ibinder3 = p.createBinderArray(); |
| assertNotNull(ibinder3); |
| for (int i = 0; i < ibinder3.length; i++) { |
| assertNotNull(ibinder3[i]); |
| assertEquals(ibinder2[i], ibinder3[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testWriteBinderList() { |
| Parcel p; |
| ArrayList<IBinder> arrayList = new ArrayList<IBinder>(); |
| ArrayList<IBinder> arrayList2 = new ArrayList<IBinder>(); |
| arrayList2.add(new Binder()); |
| arrayList2.add(new Binder()); |
| ArrayList<IBinder> arrayList3 = new ArrayList<IBinder>(); |
| arrayList3.add(new Binder()); |
| arrayList3.add(new Binder()); |
| arrayList3.add(new Binder()); |
| |
| p = Parcel.obtain(); |
| p.writeBinderList(null); |
| p.setDataPosition(0); |
| try { |
| p.readBinderList(null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| p.setDataPosition(0); |
| assertEquals(0, arrayList.size()); |
| p.readBinderList(arrayList); |
| assertEquals(0, arrayList.size()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeBinderList(arrayList2); |
| p.setDataPosition(0); |
| assertEquals(0, arrayList.size()); |
| p.readBinderList(arrayList); |
| assertEquals(2, arrayList.size()); |
| assertEquals(arrayList2, arrayList); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeBinderList(arrayList2); |
| p.setDataPosition(0); |
| assertEquals(3, arrayList3.size()); |
| p.readBinderList(arrayList3); |
| assertEquals(2, arrayList3.size()); |
| assertEquals(arrayList2, arrayList3); |
| p.recycle(); |
| } |
| |
| public void testCreateBinderArrayList() { |
| Parcel p; |
| ArrayList<IBinder> arrayList = new ArrayList<IBinder>(); |
| ArrayList<IBinder> arrayList2 = new ArrayList<IBinder>(); |
| arrayList2.add(new Binder()); |
| arrayList2.add(new Binder()); |
| ArrayList<IBinder> arrayList3; |
| ArrayList<IBinder> arrayList4; |
| |
| p = Parcel.obtain(); |
| p.writeBinderList(null); |
| p.setDataPosition(0); |
| arrayList3 = p.createBinderArrayList(); |
| assertNull(arrayList3); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeBinderList(arrayList); |
| p.setDataPosition(0); |
| arrayList3 = p.createBinderArrayList(); |
| assertNotNull(arrayList3); |
| assertEquals(0, arrayList3.size()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeBinderList(arrayList2); |
| p.setDataPosition(0); |
| arrayList4 = p.createBinderArrayList(); |
| assertNotNull(arrayList4); |
| assertEquals(arrayList2, arrayList4); |
| p.recycle(); |
| } |
| |
| public void testInterfaceArray() { |
| Parcel p; |
| MockIInterface[] iface2 = {new MockIInterface(), new MockIInterface(), null}; |
| MockIInterface[] iface3 = new MockIInterface[iface2.length]; |
| MockIInterface[] iface4 = new MockIInterface[iface2.length + 1]; |
| |
| p = Parcel.obtain(); |
| p.writeInterfaceArray(null); |
| p.setDataPosition(0); |
| try { |
| // input array shouldn't be null |
| p.readInterfaceArray(null, null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| // can't read null array |
| p.readInterfaceArray(iface3, MockIInterface::asInterface); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| // null if parcel has null array |
| assertNull(p.createInterfaceArray(MockIInterface[]::new, MockIInterface::asInterface)); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInterfaceArray(iface2); |
| p.setDataPosition(0); |
| try { |
| // input array shouldn't be null |
| p.readInterfaceArray(null, null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| // input array should be the same size |
| p.readInterfaceArray(iface4, MockIInterface::asInterface); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| try { |
| // asInterface shouldn't be null |
| p.readInterfaceArray(iface3, null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| // read into input array with the exact size |
| p.readInterfaceArray(iface3, MockIInterface::asInterface); |
| for (int i = 0; i < iface3.length; i++) { |
| assertEquals(iface2[i], iface3[i]); |
| } |
| |
| p.setDataPosition(0); |
| try { |
| // newArray/asInterface shouldn't be null |
| p.createInterfaceArray(null, null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| // create a new array from parcel |
| MockIInterface[] iface5 = |
| p.createInterfaceArray(MockIInterface[]::new, MockIInterface::asInterface); |
| assertNotNull(iface5); |
| assertEquals(iface2.length, iface5.length); |
| for (int i = 0; i < iface5.length; i++) { |
| assertEquals(iface2[i], iface5[i]); |
| } |
| p.recycle(); |
| } |
| |
| public void testInterfaceList() { |
| Parcel p; |
| ArrayList<MockIInterface> arrayList = new ArrayList<>(); |
| ArrayList<MockIInterface> arrayList2 = new ArrayList<>(); |
| ArrayList<MockIInterface> arrayList3; |
| arrayList.add(new MockIInterface()); |
| arrayList.add(new MockIInterface()); |
| arrayList.add(null); |
| |
| p = Parcel.obtain(); |
| p.writeInterfaceList(null); |
| p.setDataPosition(0); |
| try { |
| // input list shouldn't be null |
| p.readInterfaceList(null, null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| arrayList2.clear(); |
| arrayList2.add(null); |
| try { |
| // can't read null list into non-empty list |
| p.readInterfaceList(arrayList2, MockIInterface::asInterface); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| arrayList2.clear(); |
| // read null list into empty list |
| p.readInterfaceList(arrayList2, MockIInterface::asInterface); |
| assertEquals(0, arrayList2.size()); |
| |
| p.setDataPosition(0); |
| // null if parcel has null list |
| arrayList3 = p.createInterfaceArrayList(MockIInterface::asInterface); |
| assertNull(arrayList3); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeInterfaceList(arrayList); |
| p.setDataPosition(0); |
| try { |
| // input list shouldn't be null |
| p.readInterfaceList(null, null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| |
| p.setDataPosition(0); |
| arrayList2.clear(); |
| try { |
| // asInterface shouldn't be null |
| p.readInterfaceList(arrayList2, null); |
| fail("Should throw a RuntimeException"); |
| } catch (RuntimeException e) { |
| //expected |
| } |
| |
| p.setDataPosition(0); |
| arrayList2.clear(); |
| // fill a list with parcel |
| p.readInterfaceList(arrayList2, MockIInterface::asInterface); |
| assertEquals(arrayList, arrayList2); |
| |
| p.setDataPosition(0); |
| arrayList2.clear(); |
| // add one more item |
| for (int i=0; i<arrayList.size() + 1; i++) { |
| arrayList2.add(null); |
| } |
| // extra item should be discarded after read |
| p.readInterfaceList(arrayList2, MockIInterface::asInterface); |
| assertEquals(arrayList, arrayList2); |
| |
| p.setDataPosition(0); |
| // create a new ArrayList from parcel |
| arrayList3 = p.createInterfaceArrayList(MockIInterface::asInterface); |
| assertEquals(arrayList, arrayList3); |
| p.recycle(); |
| } |
| |
| public void testFixedArray() { |
| Parcel p = Parcel.obtain(); |
| |
| // test int[2][3] |
| int[][] ints = new int[][] {{1,2,3}, {4,5,6}}; |
| p.writeFixedArray(ints, 0, new int[]{2, 3}); |
| p.setDataPosition(0); |
| assertArrayEquals(ints, p.createFixedArray(int[][].class, new int[]{2, 3})); |
| int[][] readInts = new int[2][3]; |
| p.setDataPosition(0); |
| p.readFixedArray(readInts); |
| assertArrayEquals(ints, readInts); |
| |
| // test Parcelable[2][3] |
| p.setDataPosition(0); |
| Signature[][] signatures = { |
| {new Signature("1234"), new Signature("ABCD"), new Signature("abcd")}, |
| {new Signature("5678"), new Signature("EFAB"), new Signature("efab")}}; |
| p.writeFixedArray(signatures, 0, new int[]{2, 3}); |
| p.setDataPosition(0); |
| assertArrayEquals(signatures, p.createFixedArray(Signature[][].class, Signature.CREATOR, new int[]{2, 3})); |
| Signature[][] readSignatures = new Signature[2][3]; |
| p.setDataPosition(0); |
| p.readFixedArray(readSignatures, Signature.CREATOR); |
| assertArrayEquals(signatures, readSignatures); |
| |
| // test IInterface[2][3] |
| p.setDataPosition(0); |
| MockIInterface[][] interfaces = { |
| {new MockIInterface(), new MockIInterface(), new MockIInterface()}, |
| {new MockIInterface(), new MockIInterface(), new MockIInterface()}}; |
| p.writeFixedArray(interfaces, 0, new int[]{2, 3}); |
| p.setDataPosition(0); |
| MockIInterface[][] interfacesRead = p.createFixedArray(MockIInterface[][].class, |
| MockIInterface::asInterface, new int[]{2, 3}); |
| assertEquals(2, interfacesRead.length); |
| assertEquals(3, interfacesRead[0].length); |
| MockIInterface[][] mockInterfaces = new MockIInterface[2][3]; |
| p.setDataPosition(0); |
| p.readFixedArray(mockInterfaces, MockIInterface::asInterface); |
| assertArrayEquals(interfaces, mockInterfaces); |
| |
| // test null |
| p.setDataPosition(0); |
| int[][] nullInts = null; |
| p.writeFixedArray(nullInts, 0, new int[]{2, 3}); |
| p.setDataPosition(0); |
| assertNull(p.createFixedArray(int[][].class, new int[]{2, 3})); |
| |
| // reject wrong dimensions when writing |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, |
| () -> p.writeFixedArray(new int[3][2], 0, new int[]{2, 2})); |
| assertThrows(BadParcelableException.class, |
| () -> p.writeFixedArray(new int[3], 0, new int[]{3, 2})); |
| assertThrows(BadParcelableException.class, |
| () -> p.writeFixedArray(new int[3][2], 0, new int[]{3})); |
| |
| // reject wrong dimensions when reading |
| p.setDataPosition(0); |
| p.writeFixedArray(new int[2][3], 0, new int[]{2, 3}); |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.createFixedArray(int[][].class, 1, 3)); |
| assertThrows(BadParcelableException.class, () -> p.createFixedArray(int[][].class, 2, 2)); |
| |
| p.recycle(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testWriteMap() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| HashMap map = new HashMap(); |
| HashMap map2 = new HashMap(); |
| |
| p = Parcel.obtain(); |
| p.writeMap(null); |
| p.setDataPosition(0); |
| assertEquals(0, map2.size()); |
| p.readMap(map2, mcl); |
| assertEquals(0, map2.size()); |
| p.recycle(); |
| |
| map.put("string", "String"); |
| map.put("int", Integer.MAX_VALUE); |
| map.put("boolean", true); |
| p = Parcel.obtain(); |
| p.writeMap(map); |
| p.setDataPosition(0); |
| assertEquals(0, map2.size()); |
| p.readMap(map2, mcl); |
| assertEquals(3, map2.size()); |
| assertEquals("String", map.get("string")); |
| assertEquals(Integer.MAX_VALUE, map.get("int")); |
| assertEquals(true, map.get("boolean")); |
| p.recycle(); |
| } |
| |
| public void testReadMapWithClass_whenNull() { |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| p.writeMap(null); |
| HashMap<String, Intent> map = new HashMap<>(); |
| |
| p.setDataPosition(0); |
| p.readMap(map, mcl, String.class, Intent.class); |
| assertEquals(0, map.size()); |
| |
| p.recycle(); |
| } |
| |
| public void testReadMapWithClass_whenMismatchingClass() { |
| Parcel p = Parcel.obtain(); |
| ClassLoader loader = getClass().getClassLoader(); |
| HashMap<Signature, TestSubIntent> map = new HashMap<>(); |
| |
| Intent baseIntent = new Intent(); |
| map.put(new Signature("1234"), new TestSubIntent( |
| baseIntent, "test_intent1")); |
| map.put(new Signature("4321"), new TestSubIntent( |
| baseIntent, "test_intent2")); |
| p.writeMap(map); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> |
| p.readMap(new HashMap<Intent, TestSubIntent>(), loader, |
| Intent.class, TestSubIntent.class)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> |
| p.readMap(new HashMap<Signature, Signature>(), loader, |
| Signature.class, Signature.class)); |
| p.recycle(); |
| } |
| |
| public void testReadMapWithClass_whenSameClass() { |
| Parcel p = Parcel.obtain(); |
| ClassLoader loader = getClass().getClassLoader(); |
| HashMap<String, TestSubIntent> map = new HashMap<>(); |
| HashMap<String, TestSubIntent> map2 = new HashMap<>(); |
| |
| Intent baseIntent = new Intent(); |
| map.put("key1", new TestSubIntent( |
| baseIntent, "test_intent1")); |
| map.put("key2", new TestSubIntent( |
| baseIntent, "test_intent2")); |
| p.writeMap(map); |
| p.setDataPosition(0); |
| p.readMap(map2, loader, String.class, TestSubIntent.class); |
| assertEquals(map, map2); |
| |
| p.recycle(); |
| } |
| |
| public void testReadMapWithClass_whenSubClass() { |
| Parcel p = Parcel.obtain(); |
| ClassLoader loader = getClass().getClassLoader(); |
| HashMap<TestSubIntent, TestSubIntent> map = new HashMap<>(); |
| |
| Intent baseIntent = new Intent(); |
| map.put(new TestSubIntent(baseIntent, "test_intent_key1"), new TestSubIntent( |
| baseIntent, "test_intent_val1")); |
| p.writeMap(map); |
| p.setDataPosition(0); |
| HashMap<Intent, Intent> map2 = new HashMap<>(); |
| p.readMap(map2, loader, Intent.class, TestSubIntent.class); |
| assertEquals(map, map2); |
| |
| p.setDataPosition(0); |
| HashMap<Intent, Intent> map3 = new HashMap<>(); |
| p.readMap(map3, loader, TestSubIntent.class, Intent.class); |
| assertEquals(map, map3); |
| |
| p.recycle(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testReadHashMap() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| HashMap map = new HashMap(); |
| HashMap map2; |
| |
| p = Parcel.obtain(); |
| p.writeMap(null); |
| p.setDataPosition(0); |
| map2 = p.readHashMap(mcl); |
| assertNull(map2); |
| p.recycle(); |
| |
| map.put("string", "String"); |
| map.put("int", Integer.MAX_VALUE); |
| map.put("boolean", true); |
| map2 = null; |
| p = Parcel.obtain(); |
| p.writeMap(map); |
| p.setDataPosition(0); |
| map2 = p.readHashMap(mcl); |
| assertNotNull(map2); |
| assertEquals(3, map2.size()); |
| assertEquals("String", map.get("string")); |
| assertEquals(Integer.MAX_VALUE, map.get("int")); |
| assertEquals(true, map.get("boolean")); |
| p.recycle(); |
| } |
| |
| public void testReadHashMapWithClass_whenNull() { |
| Parcel p = Parcel.obtain(); |
| MockClassLoader mcl = new MockClassLoader(); |
| p.writeMap(null); |
| p.setDataPosition(0); |
| assertNull(p.readHashMap(mcl, String.class, Intent.class)); |
| |
| p.setDataPosition(0); |
| assertNull(p.readHashMap(null, String.class, Intent.class)); |
| p.recycle(); |
| } |
| |
| public void testReadHashMapWithClass_whenMismatchingClass() { |
| Parcel p = Parcel.obtain(); |
| ClassLoader loader = getClass().getClassLoader(); |
| HashMap<Signature, TestSubIntent> map = new HashMap<>(); |
| |
| Intent baseIntent = new Intent(); |
| map.put(new Signature("1234"), new TestSubIntent( |
| baseIntent, "test_intent1")); |
| map.put(new Signature("4321"), new TestSubIntent( |
| baseIntent, "test_intent2")); |
| p.writeMap(map); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> |
| p.readHashMap(loader, Intent.class, TestSubIntent.class)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> |
| p.readHashMap(loader, Signature.class, Signature.class)); |
| p.recycle(); |
| } |
| |
| public void testReadHashMapWithClass_whenSameClass() { |
| Parcel p = Parcel.obtain(); |
| ClassLoader loader = getClass().getClassLoader(); |
| HashMap<String, TestSubIntent> map = new HashMap<>(); |
| |
| Intent baseIntent = new Intent(); |
| map.put("key1", new TestSubIntent( |
| baseIntent, "test_intent1")); |
| map.put("key2", new TestSubIntent( |
| baseIntent, "test_intent2")); |
| |
| p.writeMap(map); |
| p.setDataPosition(0); |
| HashMap<String, TestSubIntent> map2 = p.readHashMap(loader, String.class, |
| TestSubIntent.class); |
| assertEquals(map, map2); |
| |
| p.setDataPosition(0); |
| HashMap<Object, Intent> map3 = p.readHashMap(loader, String.class, |
| TestSubIntent.class); |
| assertEquals(map, map3); |
| |
| p.recycle(); |
| } |
| |
| public void testReadHashMapWithClass_whenSubClass() { |
| Parcel p = Parcel.obtain(); |
| ClassLoader loader = getClass().getClassLoader(); |
| HashMap<TestSubIntent, TestSubIntent> map = new HashMap<>(); |
| |
| Intent baseIntent = new Intent(); |
| TestSubIntent test_intent_key1 = new TestSubIntent(baseIntent, "test_intent_key1"); |
| map.put(test_intent_key1, new TestSubIntent( |
| baseIntent, "test_intent_val1")); |
| p.writeMap(map); |
| p.setDataPosition(0); |
| HashMap<Intent, Intent> map2 = p.readHashMap(loader, Intent.class, TestSubIntent.class); |
| assertEquals(map, map2); |
| |
| p.setDataPosition(0); |
| HashMap<Intent, Intent> map3 = p.readHashMap(loader, TestSubIntent.class, Intent.class); |
| assertEquals(map, map3); |
| p.recycle(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testReadList() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| ArrayList arrayList = new ArrayList(); |
| |
| p = Parcel.obtain(); |
| p.writeList(null); |
| p.setDataPosition(0); |
| assertEquals(0, arrayList.size()); |
| p.readList(arrayList, mcl); |
| assertEquals(0, arrayList.size()); |
| p.recycle(); |
| |
| ArrayList arrayList2 = new ArrayList(); |
| arrayList2.add(Integer.MAX_VALUE); |
| arrayList2.add(true); |
| arrayList2.add(Long.MAX_VALUE); |
| arrayList2.add("String"); |
| arrayList2.add(Float.MAX_VALUE); |
| |
| p = Parcel.obtain(); |
| p.writeList(arrayList2); |
| p.setDataPosition(0); |
| assertEquals(0, arrayList.size()); |
| p.readList(arrayList, mcl); |
| assertEquals(5, arrayList.size()); |
| for (int i = 0; i < arrayList.size(); i++) { |
| assertEquals(arrayList.get(i), arrayList2.get(i)); |
| } |
| |
| p.recycle(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testReadListWithClass() { |
| Parcel p; |
| MockClassLoader mcl = new MockClassLoader(); |
| ArrayList<Signature> arrayList = new ArrayList(); |
| ArrayList<Signature> parcelableArrayList = new ArrayList(); |
| final String s1 = "1234567890abcdef"; |
| final String s2 = "abcdef1234567890"; |
| parcelableArrayList.add(new Signature(s1)); |
| parcelableArrayList.add(new Signature(s2)); |
| |
| p = Parcel.obtain(); |
| p.writeList(parcelableArrayList); |
| p.setDataPosition(0); |
| assertEquals(0, arrayList.size()); |
| p.readList(arrayList, mcl, Signature.class); |
| assertEquals(2, arrayList.size()); |
| for (int i = 0; i < arrayList.size(); i++) { |
| assertEquals(arrayList.get(i), parcelableArrayList.get(i)); |
| } |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readList(new ArrayList(), mcl, Intent.class)); |
| |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p.readList(new ArrayList(), mcl, Integer.class)); |
| p.recycle(); |
| |
| ArrayList<String> stringArrayList = new ArrayList(); |
| stringArrayList.add(s1); |
| stringArrayList.add(s2); |
| Parcel p1 = Parcel.obtain(); |
| p1.writeList(stringArrayList); |
| |
| p1.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> p1.readList(new ArrayList(), mcl, Integer.class)); |
| p1.recycle(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testReadListWithSubClass() { |
| Parcel p; |
| ArrayList<Intent> arrayList = new ArrayList(); |
| ArrayList<Intent> arrayList2 = new ArrayList(); |
| ArrayList<Intent> parcelableArrayList = new ArrayList(); |
| final Intent baseIntent = new Intent(); |
| final TestSubIntent testSubIntent = new TestSubIntent(baseIntent, "1234567890abcdef"); |
| final TestSubIntent testSubIntent1 = new TestSubIntent(baseIntent, "abcdef1234567890"); |
| parcelableArrayList.add(testSubIntent); |
| parcelableArrayList.add(testSubIntent1); |
| |
| p = Parcel.obtain(); |
| p.writeList(parcelableArrayList); |
| p.setDataPosition(0); |
| assertEquals(0, arrayList.size()); |
| p.readList(arrayList, getClass().getClassLoader(), Intent.class); |
| assertEquals(2, arrayList.size()); |
| for (int i = 0; i < arrayList.size(); i++) { |
| assertEquals(arrayList.get(i), parcelableArrayList.get(i)); |
| } |
| |
| p.setDataPosition(0); |
| assertEquals(0, arrayList2.size()); |
| p.readList(arrayList2, getClass().getClassLoader(), TestSubIntent.class); |
| assertEquals(2, arrayList2.size()); |
| for (int i = 0; i < arrayList2.size(); i++) { |
| assertEquals(arrayList2.get(i), parcelableArrayList.get(i)); |
| } |
| |
| p.recycle(); |
| } |
| |
| public void testBinderDataProtection() { |
| Parcel p; |
| IBinder b = new Binder(); |
| |
| p = Parcel.obtain(); |
| final int firstIntPos = p.dataPosition(); |
| p.writeInt(1); |
| p.writeStrongBinder(b); |
| final int secondIntPos = p.dataPosition(); |
| p.writeInt(2); |
| p.writeStrongBinder(b); |
| final int thirdIntPos = p.dataPosition(); |
| p.writeInt(3); |
| |
| for (int pos = 0; pos <= thirdIntPos; pos++) { |
| p.setDataPosition(pos); |
| int value = p.readInt(); |
| |
| // WARNING: this is using unstable APIs: these positions aren't guaranteed |
| if (firstIntPos - 4 <= pos && pos <= firstIntPos) continue; |
| if (secondIntPos - 4 <= pos && pos <= secondIntPos) continue; |
| if (thirdIntPos - 4 <= pos && pos <= thirdIntPos) continue; |
| |
| // All other read attempts cross into protected data and will return 0 |
| assertEquals(0, value); |
| } |
| |
| p.recycle(); |
| } |
| |
| public void testBinderDataProtectionIncrements() { |
| Parcel p; |
| IBinder b = new Binder(); |
| |
| p = Parcel.obtain(); |
| final int firstIntPos = p.dataPosition(); |
| p.writeInt(1); |
| p.writeStrongBinder(b); |
| final int secondIntPos = p.dataPosition(); |
| p.writeInt(2); |
| p.writeStrongBinder(b); |
| final int thirdIntPos = p.dataPosition(); |
| p.writeInt(3); |
| final int end = p.dataPosition(); |
| |
| p.setDataPosition(0); |
| int pos; |
| do { |
| pos = p.dataPosition(); |
| int value = p.readInt(); |
| |
| // WARNING: this is using unstable APIs: these positions aren't guaranteed |
| if (firstIntPos - 4 <= pos && pos <= firstIntPos) continue; |
| if (secondIntPos - 4 <= pos && pos <= secondIntPos) continue; |
| if (thirdIntPos - 4 <= pos && pos <= thirdIntPos) continue; |
| |
| assertEquals(0, value); |
| } while(pos < end); |
| |
| p.recycle(); |
| } |
| |
| private class MockClassLoader extends ClassLoader { |
| public MockClassLoader() { |
| super(); |
| } |
| } |
| |
| private static class MockIInterface implements IInterface { |
| public Binder binder; |
| private static final String DESCRIPTOR = "MockIInterface"; |
| public MockIInterface() { |
| binder = new Binder(); |
| binder.attachInterface(this, DESCRIPTOR); |
| } |
| |
| public IBinder asBinder() { |
| return binder; |
| } |
| |
| public static MockIInterface asInterface(IBinder binder) { |
| if (binder != null) { |
| IInterface iface = binder.queryLocalInterface(DESCRIPTOR); |
| if (iface != null && iface instanceof MockIInterface) { |
| return (MockIInterface) iface; |
| } |
| } |
| return null; |
| } |
| } |
| |
| private static boolean parcelableWithBadCreatorInitializerHasRun; |
| private static boolean invalidCreatorIntializerHasRun; |
| |
| /** |
| * A class that would be Parcelable except that it doesn't have a CREATOR field declared to be |
| * of the correct type. |
| */ |
| @SuppressWarnings("unused") // Referenced via reflection only |
| private static class ParcelableWithBadCreator implements Parcelable { |
| |
| static { |
| ParcelTest.parcelableWithBadCreatorInitializerHasRun = true; |
| } |
| |
| private static class InvalidCreator |
| implements Parcelable.Creator<ParcelableWithBadCreator> { |
| |
| static { |
| invalidCreatorIntializerHasRun = true; |
| } |
| |
| @Override |
| public ParcelableWithBadCreator createFromParcel(Parcel source) { |
| return null; |
| } |
| |
| @Override |
| public ParcelableWithBadCreator[] newArray(int size) { |
| return new ParcelableWithBadCreator[0]; |
| } |
| |
| } |
| |
| // Invalid declaration: Must be declared as Parcelable.Creator or a subclass. |
| public static Object CREATOR = new InvalidCreator(); |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| |
| } |
| } |
| |
| // http://b/1171613 |
| public void testBadStream_invalidCreator() { |
| Parcel parcel = Parcel.obtain(); |
| // Create an invalid stream by manipulating the Parcel. |
| parcel.writeString(getClass().getName() + "$ParcelableWithBadCreator"); |
| byte[] badData = parcel.marshall(); |
| parcel.recycle(); |
| |
| // Now try to read the bad data. |
| parcel = Parcel.obtain(); |
| parcel.unmarshall(badData, 0, badData.length); |
| parcel.setDataPosition(0); |
| try { |
| parcel.readParcelable(getClass().getClassLoader()); |
| fail(); |
| } catch (BadParcelableException expected) { |
| } finally { |
| parcel.recycle(); |
| } |
| |
| assertFalse(invalidCreatorIntializerHasRun); |
| assertFalse(parcelableWithBadCreatorInitializerHasRun); |
| } |
| |
| private static boolean doesNotImplementParcelableInitializerHasRun; |
| |
| /** A class that would be Parcelable except that it does not implement Parcelable. */ |
| @SuppressWarnings("unused") // Referenced via reflection only |
| private static class DoesNotImplementParcelable { |
| |
| static { |
| doesNotImplementParcelableInitializerHasRun = true; |
| } |
| |
| public static Parcelable.Creator<Object> CREATOR = new Parcelable.Creator<Object>() { |
| @Override |
| public Object createFromParcel(Parcel source) { |
| return new DoesNotImplementParcelable(); |
| } |
| |
| @Override |
| public Object[] newArray(int size) { |
| return new Object[size]; |
| } |
| }; |
| } |
| |
| // http://b/1171613 |
| public void testBadStream_objectDoesNotImplementParcelable() { |
| Parcel parcel = Parcel.obtain(); |
| // Create an invalid stream by manipulating the Parcel. |
| parcel.writeString(getClass().getName() + "$DoesNotImplementParcelable"); |
| byte[] badData = parcel.marshall(); |
| parcel.recycle(); |
| |
| // Now try to read the bad data. |
| parcel = Parcel.obtain(); |
| parcel.unmarshall(badData, 0, badData.length); |
| parcel.setDataPosition(0); |
| try { |
| parcel.readParcelable(getClass().getClassLoader()); |
| fail(); |
| } catch (BadParcelableException expected) { |
| } finally { |
| parcel.recycle(); |
| } |
| |
| assertFalse(doesNotImplementParcelableInitializerHasRun); |
| } |
| |
| public static class SimpleParcelable implements Parcelable { |
| private final int value; |
| |
| public SimpleParcelable(int value) { |
| this.value = value; |
| } |
| |
| private SimpleParcelable(Parcel in) { |
| this.value = in.readInt(); |
| } |
| |
| public int getValue() { |
| return value; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel out, int flags) { |
| out.writeInt(value); |
| } |
| |
| public static Parcelable.Creator<SimpleParcelable> CREATOR = |
| new Parcelable.Creator<SimpleParcelable>() { |
| |
| @Override |
| public SimpleParcelable createFromParcel(Parcel source) { |
| return new SimpleParcelable(source); |
| } |
| |
| @Override |
| public SimpleParcelable[] newArray(int size) { |
| return new SimpleParcelable[size]; |
| } |
| }; |
| } |
| |
| public void testReadWriteParcellableList() { |
| Parcel parcel = Parcel.obtain(); |
| |
| ArrayList<SimpleParcelable> list = new ArrayList<>(); |
| list.add(new SimpleParcelable(57)); |
| |
| // Writing a |null| list to a parcel should work, and reading it back |
| // from a parcel should clear the target list. |
| parcel.writeParcelableList(null, 0); |
| parcel.setDataPosition(0); |
| parcel.readParcelableList(list, SimpleParcelable.class.getClassLoader()); |
| assertEquals(0, list.size()); |
| |
| list.clear(); |
| list.add(new SimpleParcelable(42)); |
| list.add(new SimpleParcelable(56)); |
| |
| parcel.setDataPosition(0); |
| parcel.writeParcelableList(list, 0); |
| |
| // Populate the list with a value, we will later assert that the |
| // value has been removed. |
| list.clear(); |
| list.add(new SimpleParcelable(100)); |
| |
| parcel.setDataPosition(0); |
| parcel.readParcelableList(list, SimpleParcelable.class.getClassLoader()); |
| |
| assertEquals(2, list.size()); |
| assertEquals(42, list.get(0).getValue()); |
| assertEquals(56, list.get(1).getValue()); |
| } |
| |
| public void testReadParcelableListWithClass_whenNull(){ |
| final Parcel p = Parcel.obtain(); |
| ArrayList<Intent> list = new ArrayList<>(); |
| list.add(new Intent("test")); |
| |
| p.writeParcelableList(null, 0); |
| p.setDataPosition(0); |
| p.readParcelableList(list, getClass().getClassLoader(), Intent.class); |
| assertEquals(0, list.size()); |
| p.recycle(); |
| } |
| |
| public void testReadParcelableListWithClass_whenMismatchingClass(){ |
| final Parcel p = Parcel.obtain(); |
| ArrayList<Signature> list = new ArrayList<>(); |
| ArrayList<Intent> list1 = new ArrayList<>(); |
| list.add(new Signature("1234")); |
| p.writeParcelableList(list, 0); |
| p.setDataPosition(0); |
| assertThrows(BadParcelableException.class, () -> |
| p.readParcelableList(list1, getClass().getClassLoader(), Intent.class)); |
| |
| p.recycle(); |
| } |
| |
| public void testReadParcelableListWithClass_whenSameClass(){ |
| final Parcel p = Parcel.obtain(); |
| ArrayList<Signature> list = new ArrayList<>(); |
| ArrayList<Signature> list1 = new ArrayList<>(); |
| list.add(new Signature("1234")); |
| list.add(new Signature("4321")); |
| p.writeParcelableList(list, 0); |
| p.setDataPosition(0); |
| p.readParcelableList(list1, getClass().getClassLoader(), Signature.class); |
| |
| assertEquals(list, list1); |
| p.recycle(); |
| } |
| |
| public void testReadParcelableListWithClass_whenSubClass(){ |
| final Parcel p = Parcel.obtain(); |
| final Intent baseIntent = new Intent(); |
| |
| ArrayList<Intent> intentArrayList = new ArrayList<>(); |
| ArrayList<Intent> intentArrayList1 = new ArrayList<>(); |
| ArrayList<Intent> intentArrayList2 = new ArrayList<>(); |
| |
| intentArrayList.add(new TestSubIntent(baseIntent, "1234567890abcdef")); |
| intentArrayList.add(null); |
| intentArrayList.add(new TestSubIntent(baseIntent, "abcdef1234567890")); |
| |
| p.writeParcelableList(intentArrayList, 0); |
| p.setDataPosition(0); |
| p.readParcelableList(intentArrayList1, getClass().getClassLoader(), Intent.class); |
| assertEquals(intentArrayList, intentArrayList1); |
| |
| p.setDataPosition(0); |
| p.readParcelableList(intentArrayList2, getClass().getClassLoader(), TestSubIntent.class); |
| assertEquals(intentArrayList, intentArrayList2); |
| p.recycle(); |
| } |
| |
| // http://b/35384981 |
| public void testCreateArrayWithTruncatedParcel() { |
| Parcel parcel = Parcel.obtain(); |
| parcel.writeByteArray(new byte[] { 'a', 'b' }); |
| byte[] marshalled = parcel.marshall(); |
| |
| // Test that createByteArray returns null with a truncated parcel. |
| parcel = Parcel.obtain(); |
| parcel.unmarshall(marshalled, 0, marshalled.length); |
| parcel.setDataPosition(0); |
| // Shorten the data size by 2 to remove padding at the end of the array. |
| parcel.setDataSize(marshalled.length - 2); |
| assertNull(parcel.createByteArray()); |
| |
| // Test that readByteArray returns null with a truncated parcel. |
| parcel = Parcel.obtain(); |
| parcel.unmarshall(marshalled, 0, marshalled.length); |
| parcel.setDataSize(marshalled.length - 2); |
| try { |
| parcel.readByteArray(new byte[2]); |
| fail(); |
| } catch (RuntimeException expected) { |
| } |
| } |
| |
| public void testMaliciousMapWrite() { |
| class MaliciousMap<K, V> extends HashMap<K, V> { |
| public int fakeSize = 0; |
| public boolean armed = false; |
| |
| class FakeEntrySet extends HashSet<Entry<K, V>> { |
| public FakeEntrySet(Collection<? extends Entry<K, V>> c) { |
| super(c); |
| } |
| |
| @Override |
| public int size() { |
| if (armed) { |
| // Only return fake size on next call, to mitigate unexpected behavior. |
| armed = false; |
| return fakeSize; |
| } else { |
| return super.size(); |
| } |
| } |
| } |
| |
| @Override |
| public Set<Map.Entry<K, V>> entrySet() { |
| return new FakeEntrySet(super.entrySet()); |
| } |
| } |
| |
| Parcel parcel = Parcel.obtain(); |
| |
| // Fake having more Map entries than there really are |
| MaliciousMap map = new MaliciousMap<String, String>(); |
| map.fakeSize = 1; |
| map.armed = true; |
| try { |
| parcel.writeMap(map); |
| fail("Should have thrown a BadParcelableException"); |
| } catch (BadParcelableException bpe) { |
| // good |
| } |
| |
| // Fake having fewer Map entries than there really are |
| map = new MaliciousMap<String, String>(); |
| map.put("key", "value"); |
| map.fakeSize = 0; |
| map.armed = true; |
| try { |
| parcel.writeMap(map); |
| fail("Should have thrown a BadParcelableException"); |
| } catch (BadParcelableException bpe) { |
| // good |
| } |
| } |
| |
| public static class ParcelExceptionConnection extends AbstractFuture<IParcelExceptionService> |
| implements ServiceConnection { |
| @Override |
| public void onServiceConnected(ComponentName name, IBinder service) { |
| set(IParcelExceptionService.Stub.asInterface(service)); |
| } |
| |
| @Override |
| public void onServiceDisconnected(ComponentName name) { |
| } |
| |
| @Override |
| public IParcelExceptionService get() throws InterruptedException, ExecutionException { |
| try { |
| return get(5, TimeUnit.SECONDS); |
| } catch (TimeoutException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| } |
| |
| public void testExceptionOverwritesObject() throws Exception { |
| final Intent intent = new Intent(); |
| intent.setComponent(new ComponentName( |
| "android.os.cts", "android.os.cts.ParcelExceptionService")); |
| |
| final ParcelExceptionConnection connection = new ParcelExceptionConnection(); |
| |
| mContext.startService(intent); |
| assertTrue(mContext.bindService(intent, connection, |
| Context.BIND_ABOVE_CLIENT | Context.BIND_EXTERNAL_SERVICE)); |
| |
| |
| Parcel data = Parcel.obtain(); |
| Parcel reply = Parcel.obtain(); |
| data.writeInterfaceToken("android.os.cts.IParcelExceptionService"); |
| IParcelExceptionService service = connection.get(); |
| try { |
| assertTrue("Transaction failed", service.asBinder().transact( |
| IParcelExceptionService.Stub.TRANSACTION_writeBinderThrowException, data, reply, |
| 0)); |
| } catch (Exception e) { |
| fail("Exception caught from transaction: " + e); |
| } |
| reply.setDataPosition(0); |
| assertTrue("Exception should have occurred on service-side", |
| reply.readExceptionCode() != 0); |
| assertNull("Binder should have been overwritten by the exception", |
| reply.readStrongBinder()); |
| } |
| |
| private static class TestSubIntent extends Intent { |
| private final String mString; |
| |
| public TestSubIntent(Intent baseIntent, String s) { |
| super(baseIntent); |
| mString = s; |
| } |
| |
| public void writeToParcel(Parcel dest, int parcelableFlags) { |
| super.writeToParcel(dest, parcelableFlags); |
| dest.writeString(mString); |
| } |
| |
| TestSubIntent(Parcel in) { |
| readFromParcel(in); |
| mString = in.readString(); |
| } |
| |
| public static final Creator<TestSubIntent> CREATOR = new Creator<TestSubIntent>() { |
| public TestSubIntent createFromParcel(Parcel source) { |
| return new TestSubIntent(source); |
| } |
| |
| @Override |
| public TestSubIntent[] newArray(int size) { |
| return new TestSubIntent[size]; |
| } |
| }; |
| |
| @Override |
| public boolean equals(Object obj) { |
| final TestSubIntent other = (TestSubIntent) obj; |
| return mString.equals(other.mString); |
| } |
| |
| @Override |
| public int hashCode() { |
| return mString.hashCode(); |
| } |
| } |
| |
| private static class TestSubException extends Exception{ |
| public TestSubException(String msg) { |
| super(msg); |
| } |
| } |
| |
| public static class ParcelObjectFreeService extends Service { |
| |
| @Override |
| public IBinder onBind(Intent intent) { |
| return new Binder(); |
| } |
| |
| @Override |
| public void onCreate() { |
| super.onCreate(); |
| |
| Parcel parcel = Parcel.obtain(); |
| |
| // Construct parcel with object in it. |
| parcel.writeInt(1); |
| final int pos = parcel.dataPosition(); |
| parcel.writeStrongBinder(new Binder()); |
| |
| // wipe out the object by setting data size |
| parcel.setDataSize(pos); |
| |
| // recycle the parcel. This should not cause a native segfault |
| parcel.recycle(); |
| } |
| |
| public static class Connection extends AbstractFuture<IBinder> |
| implements ServiceConnection { |
| |
| @Override |
| public void onServiceConnected(ComponentName name, IBinder service) { |
| set(service); |
| } |
| |
| @Override |
| public void onServiceDisconnected(ComponentName name) { |
| } |
| |
| @Override |
| public IBinder get() throws InterruptedException, ExecutionException { |
| try { |
| return get(5, TimeUnit.SECONDS); |
| } catch (TimeoutException e) { |
| return null; |
| } |
| } |
| } |
| } |
| |
| public void testObjectDoubleFree() throws Exception { |
| |
| final Intent intent = new Intent(); |
| intent.setComponent(new ComponentName( |
| "android.os.cts", "android.os.cts.ParcelTest$ParcelObjectFreeService")); |
| |
| final ParcelObjectFreeService.Connection connection = |
| new ParcelObjectFreeService.Connection(); |
| |
| mContext.startService(intent); |
| assertTrue(mContext.bindService(intent, connection, |
| Context.BIND_ABOVE_CLIENT | Context.BIND_EXTERNAL_SERVICE)); |
| |
| assertNotNull("Service should have started without crashing.", connection.get()); |
| } |
| |
| @AsbSecurityTest(cveBugId = 140419401) |
| public void testObjectResize() throws Exception { |
| Parcel p; |
| IBinder b1 = new Binder(); |
| IBinder b2 = new Binder(); |
| |
| p = Parcel.obtain(); |
| p.writeStrongBinder(b1); |
| p.setDataSize(0); |
| p.writeStrongBinder(b2); |
| |
| p.setDataPosition(0); |
| assertEquals("Object in parcel should match the binder written after the resize", b2, |
| p.readStrongBinder()); |
| p.recycle(); |
| |
| p = Parcel.obtain(); |
| p.writeStrongBinder(b1); |
| final int secondBinderPos = p.dataPosition(); |
| p.writeStrongBinder(b1); |
| p.setDataSize(secondBinderPos); |
| p.writeStrongBinder(b2); |
| |
| p.setDataPosition(0); |
| assertEquals("Object at the start of the parcel parcel should match the first binder", b1, |
| p.readStrongBinder()); |
| assertEquals("Object in parcel should match the binder written after the resize", b2, |
| p.readStrongBinder()); |
| p.recycle(); |
| } |
| |
| public void testFlags() { |
| Parcel p; |
| |
| p = Parcel.obtain(); |
| assertEquals(0, p.getFlags()); |
| p.setPropagateAllowBlocking(); |
| assertEquals(Parcel.FLAG_PROPAGATE_ALLOW_BLOCKING, p.getFlags()); |
| |
| // recycle / obtain should clear the flag. |
| p.recycle(); |
| p = Parcel.obtain(); |
| assertEquals(0, p.getFlags()); |
| } |
| } |