1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.app.appsearch.safeparcel; 17 18 import static com.google.common.truth.Truth.assertThat; 19 20 import android.os.Bundle; 21 import android.os.Parcel; 22 import android.util.SparseArray; 23 import android.util.SparseBooleanArray; 24 import android.util.SparseIntArray; 25 import android.util.SparseLongArray; 26 27 import androidx.test.ext.junit.runners.AndroidJUnit4; 28 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 32 @RunWith(AndroidJUnit4.class) 33 public final class SafeParcelableSparseArrayTest { 34 private static final int TEST_ID = 42; 35 private static final String BUNDLE_KEY = "test_bundle_key"; 36 37 private final Parcel mParcel = Parcel.obtain(); 38 newTestBundle(int key)39 private static Bundle newTestBundle(int key) { 40 Bundle b = new Bundle(); 41 b.putInt(BUNDLE_KEY, key); 42 return b; 43 } 44 assertTestBundleEquals(Bundle expected, Bundle actual)45 private static void assertTestBundleEquals(Bundle expected, Bundle actual) { 46 assertThat(actual.getInt(BUNDLE_KEY)).isEqualTo(expected.getInt(BUNDLE_KEY)); 47 } 48 newBundleSparseArray(int[] keys)49 private static SparseArray<Bundle> newBundleSparseArray(int[] keys) { 50 SparseArray<Bundle> sparseArray = new SparseArray<>(keys.length); 51 for (int i = 0; i < keys.length; i++) { 52 sparseArray.put(keys[i], newTestBundle(keys[i])); 53 } 54 return sparseArray; 55 } 56 57 @Test testReadWriteBytesSparseArray()58 public void testReadWriteBytesSparseArray() { 59 // Create SparseArray. 60 SparseArray<byte[]> sparseArray = new SparseArray<>(); 61 sparseArray.append(20, new byte[] {1}); 62 sparseArray.append(200, new byte[] {2}); 63 64 SafeParcelWriter.writeByteArraySparseArray( 65 mParcel, TEST_ID, sparseArray, /* writeNull= */ false); 66 67 int header = prepareToReadFromParcel(); 68 SparseArray<byte[]> readSparseArray = 69 SafeParcelReader.createByteArraySparseArray(mParcel, header); 70 71 assertByteArrayEquals(sparseArray, readSparseArray); 72 } 73 74 @Test testReadWriteBundleSparseArray()75 public void testReadWriteBundleSparseArray() { 76 // Create SparseArray. 77 int[] keys = new int[] {0, 5, 10, 300, 5000}; 78 SparseArray<Bundle> sparseArray = newBundleSparseArray(keys); 79 80 SafeParcelWriter.writeTypedSparseArray( 81 mParcel, TEST_ID, sparseArray, /* writeNull= */ false); 82 83 int header = prepareToReadFromParcel(); 84 SparseArray<Bundle> readSparseArray = 85 SafeParcelReader.createTypedSparseArray(mParcel, header, Bundle.CREATOR); 86 87 assertTestBundleEquals(sparseArray, readSparseArray); 88 } 89 create(T[] values)90 private static <T> SparseArray<T> create(T[] values) { 91 SparseArray<T> result = new SparseArray<>(); 92 int key = 0; 93 for (T value : values) { 94 result.append(key, value); 95 key += 2; 96 } 97 return result; 98 } 99 createSparseBooleanArray(boolean[] values)100 private static SparseBooleanArray createSparseBooleanArray(boolean[] values) { 101 SparseBooleanArray result = new SparseBooleanArray(); 102 int key = 0; 103 for (boolean value : values) { 104 result.append(key, value); 105 key += 2; 106 } 107 return result; 108 } 109 createSparseIntArray(int[] values)110 private static SparseIntArray createSparseIntArray(int[] values) { 111 SparseIntArray result = new SparseIntArray(); 112 int key = 0; 113 for (int value : values) { 114 result.append(key, value); 115 key += 2; 116 } 117 return result; 118 } 119 createSparseLongArray(long[] values)120 private static SparseLongArray createSparseLongArray(long[] values) { 121 SparseLongArray result = new SparseLongArray(); 122 int key = 0; 123 for (long value : values) { 124 result.append(key, value); 125 key += 2; 126 } 127 return result; 128 } 129 130 @Test testReadWriteSafeParcelableWithSparseArray()131 public void testReadWriteSafeParcelableWithSparseArray() { 132 // Create SafeParcelable. 133 SparseBooleanArray booleans = createSparseBooleanArray(new boolean[] {false, true, true}); 134 SparseIntArray integers = createSparseIntArray(new int[] {100, 1000}); 135 SparseLongArray longs = createSparseLongArray(new long[] {1000L, 20L}); 136 SparseArray<Float> floats = create(new Float[] {3.1f, 3.14f}); 137 SparseArray<Double> doubles = create(new Double[] {3.14, 3.1}); 138 SparseArray<String> strings = create(new String[] {"foo", "bar"}); 139 SparseArray<Bundle> bundles = newBundleSparseArray(new int[] {3, 7, 11}); 140 SparseArray<byte[]> bytes = create(new byte[][] {new byte[] {1}, new byte[] {42}}); 141 TestSafeParcelableWithSparseArray val = 142 new TestSafeParcelableWithSparseArray( 143 booleans, integers, longs, floats, doubles, strings, bundles, bytes); 144 145 SafeParcelWriter.writeParcelable(mParcel, TEST_ID, val, 0, false); 146 147 int header = prepareToReadFromParcel(); 148 TestSafeParcelableWithSparseArray readVal = 149 SafeParcelReader.createParcelable( 150 mParcel, header, TestSafeParcelableWithSparseArray.CREATOR); 151 152 assertEquals(val.mBooleans, readVal.mBooleans); 153 assertEquals(val.mIntegers, readVal.mIntegers); 154 assertEquals(val.mLongs, readVal.mLongs); 155 assertEquals(val.mFloats, readVal.mFloats); 156 assertEquals(val.mDoubles, readVal.mDoubles); 157 assertEquals(val.mStrings, readVal.mStrings); 158 assertTestBundleEquals(val.mBundles, readVal.mBundles); 159 assertByteArrayEquals(val.mBytes, readVal.mBytes); 160 } 161 assertEquals(SparseIntArray expected, SparseIntArray actual)162 private static void assertEquals(SparseIntArray expected, SparseIntArray actual) { 163 assertThat(actual.size()).isEqualTo(expected.size()); 164 for (int i = 0; i < expected.size(); i++) { 165 assertThat(actual.keyAt(i)).isEqualTo(expected.keyAt(i)); 166 assertThat(actual.valueAt(i)).isEqualTo(expected.valueAt(i)); 167 } 168 } 169 assertEquals(SparseLongArray expected, SparseLongArray actual)170 private static void assertEquals(SparseLongArray expected, SparseLongArray actual) { 171 assertThat(actual.size()).isEqualTo(expected.size()); 172 for (int i = 0; i < expected.size(); i++) { 173 assertThat(actual.keyAt(i)).isEqualTo(expected.keyAt(i)); 174 assertThat(actual.valueAt(i)).isEqualTo(expected.valueAt(i)); 175 } 176 } 177 assertEquals(SparseBooleanArray expected, SparseBooleanArray actual)178 private static void assertEquals(SparseBooleanArray expected, SparseBooleanArray actual) { 179 assertThat(actual.size()).isEqualTo(expected.size()); 180 for (int i = 0; i < expected.size(); i++) { 181 assertThat(actual.keyAt(i)).isEqualTo(expected.keyAt(i)); 182 assertThat(actual.valueAt(i)).isEqualTo(expected.valueAt(i)); 183 } 184 } 185 assertSizeEquals(SparseArray<T> expected, SparseArray<T> actual)186 private static <T> void assertSizeEquals(SparseArray<T> expected, SparseArray<T> actual) { 187 if (expected == null) { 188 assertThat(actual).isNull(); 189 return; 190 } 191 assertThat(actual).isNotNull(); 192 assertThat(actual.size()).isEqualTo(expected.size()); 193 } 194 assertEquals(SparseArray<T> expected, SparseArray<T> actual)195 private static <T> void assertEquals(SparseArray<T> expected, SparseArray<T> actual) { 196 assertSizeEquals(expected, actual); 197 for (int i = 0; i < expected.size(); i++) { 198 assertThat(actual.keyAt(i)).isEqualTo(expected.keyAt(i)); 199 assertThat(actual.valueAt(i)).isEqualTo(expected.valueAt(i)); 200 } 201 } 202 assertByteArrayEquals( SparseArray<byte[]> expected, SparseArray<byte[]> actual)203 private static void assertByteArrayEquals( 204 SparseArray<byte[]> expected, SparseArray<byte[]> actual) { 205 assertSizeEquals(expected, actual); 206 for (int i = 0; i < expected.size(); i++) { 207 assertThat(actual.keyAt(i)).isEqualTo(expected.keyAt(i)); 208 assertThat(actual.valueAt(i)).isEqualTo(expected.valueAt(i)); 209 } 210 } 211 assertTestBundleEquals( SparseArray<Bundle> expected, SparseArray<Bundle> actual)212 private static void assertTestBundleEquals( 213 SparseArray<Bundle> expected, SparseArray<Bundle> actual) { 214 assertSizeEquals(expected, actual); 215 for (int i = 0; i < expected.size(); i++) { 216 assertThat(actual.keyAt(i)).isEqualTo(expected.keyAt(i)); 217 assertTestBundleEquals(expected.valueAt(i), actual.valueAt(i)); 218 } 219 } 220 221 // Reset the data position and return the header. prepareToReadFromParcel()222 private int prepareToReadFromParcel() { 223 mParcel.setDataPosition(0); 224 return SafeParcelReader.readHeader(mParcel); 225 } 226 } 227