1 /* 2 * Copyright (C) 2020 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 17 package android.net.vcn.util; 18 19 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertTrue; 23 24 import android.os.PersistableBundle; 25 26 import androidx.test.filters.SmallTest; 27 import androidx.test.runner.AndroidJUnit4; 28 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.LinkedHashMap; 35 import java.util.List; 36 import java.util.Objects; 37 38 @RunWith(AndroidJUnit4.class) 39 @SmallTest 40 public class PersistableBundleUtilsTest { 41 private static final String TEST_KEY = "testKey"; 42 private static final String TEST_STRING_PREFIX = "testString"; 43 private static final int[] TEST_INT_ARRAY = new int[] {0, 1, 2, 3, 4}; 44 45 private static final int NUM_COLLECTION_ENTRIES = 10; 46 47 private static class TestKey { 48 private static final String TEST_INTEGER_KEY = 49 "mTestInteger"; // Purposely colliding with keys of test class to ensure namespacing 50 private final int mTestInteger; 51 TestKey(int testInteger)52 TestKey(int testInteger) { 53 mTestInteger = testInteger; 54 } 55 TestKey(PersistableBundle in)56 TestKey(PersistableBundle in) { 57 mTestInteger = in.getInt(TEST_INTEGER_KEY); 58 } 59 toPersistableBundle()60 public PersistableBundle toPersistableBundle() { 61 final PersistableBundle result = new PersistableBundle(); 62 63 result.putInt(TEST_INTEGER_KEY, mTestInteger); 64 65 return result; 66 } 67 68 @Override hashCode()69 public int hashCode() { 70 return Objects.hash(mTestInteger); 71 } 72 73 @Override equals(Object o)74 public boolean equals(Object o) { 75 if (!(o instanceof TestKey)) { 76 return false; 77 } 78 79 final TestKey other = (TestKey) o; 80 return mTestInteger == other.mTestInteger; 81 } 82 } 83 84 private static class TestClass { 85 private static final String TEST_INTEGER_KEY = "mTestInteger"; 86 private final int mTestInteger; 87 88 private static final String TEST_INT_ARRAY_KEY = "mTestIntArray"; 89 private final int[] mTestIntArray; 90 91 private static final String TEST_STRING_KEY = "mTestString"; 92 private final String mTestString; 93 94 private static final String TEST_PERSISTABLE_BUNDLE_KEY = "mTestPersistableBundle"; 95 private final PersistableBundle mTestPersistableBundle; 96 TestClass( int testInteger, int[] testIntArray, String testString, PersistableBundle testPersistableBundle)97 TestClass( 98 int testInteger, 99 int[] testIntArray, 100 String testString, 101 PersistableBundle testPersistableBundle) { 102 mTestInteger = testInteger; 103 mTestIntArray = testIntArray; 104 mTestString = testString; 105 mTestPersistableBundle = testPersistableBundle; 106 } 107 TestClass(PersistableBundle in)108 TestClass(PersistableBundle in) { 109 mTestInteger = in.getInt(TEST_INTEGER_KEY); 110 mTestIntArray = in.getIntArray(TEST_INT_ARRAY_KEY); 111 mTestString = in.getString(TEST_STRING_KEY); 112 mTestPersistableBundle = in.getPersistableBundle(TEST_PERSISTABLE_BUNDLE_KEY); 113 } 114 toPersistableBundle()115 public PersistableBundle toPersistableBundle() { 116 final PersistableBundle result = new PersistableBundle(); 117 118 result.putInt(TEST_INTEGER_KEY, mTestInteger); 119 result.putIntArray(TEST_INT_ARRAY_KEY, mTestIntArray); 120 result.putString(TEST_STRING_KEY, mTestString); 121 result.putPersistableBundle(TEST_PERSISTABLE_BUNDLE_KEY, mTestPersistableBundle); 122 123 return result; 124 } 125 126 @Override hashCode()127 public int hashCode() { 128 return Objects.hash( 129 mTestInteger, 130 Arrays.hashCode(mTestIntArray), 131 mTestString, 132 mTestPersistableBundle); 133 } 134 135 @Override equals(Object o)136 public boolean equals(Object o) { 137 if (!(o instanceof TestClass)) { 138 return false; 139 } 140 141 final TestClass other = (TestClass) o; 142 143 // TODO: Add a proper equals() to PersistableBundle. But in the meantime, force 144 // TODO: unparcelling in order to allow test comparison. 145 if (mTestPersistableBundle.size() != other.mTestPersistableBundle.size()) { 146 return false; 147 } 148 149 return mTestInteger == other.mTestInteger 150 && Arrays.equals(mTestIntArray, other.mTestIntArray) 151 && mTestString.equals(other.mTestString) 152 && mTestPersistableBundle.kindofEquals(other.mTestPersistableBundle); 153 } 154 } 155 156 @Test testListConversionLossless()157 public void testListConversionLossless() throws Exception { 158 final List<TestClass> sourceList = new ArrayList<>(); 159 for (int i = 0; i < NUM_COLLECTION_ENTRIES; i++) { 160 final PersistableBundle innerBundle = new PersistableBundle(); 161 innerBundle.putInt(TEST_KEY, i); 162 163 sourceList.add(new TestClass(i, TEST_INT_ARRAY, TEST_STRING_PREFIX + i, innerBundle)); 164 } 165 166 final PersistableBundle bundled = 167 PersistableBundleUtils.fromList(sourceList, TestClass::toPersistableBundle); 168 final List<TestClass> resultList = PersistableBundleUtils.toList(bundled, TestClass::new); 169 170 assertEquals(sourceList, resultList); 171 } 172 173 @Test testMapConversionLossless()174 public void testMapConversionLossless() throws Exception { 175 final LinkedHashMap<TestKey, TestClass> sourceMap = new LinkedHashMap<>(); 176 for (int i = 0; i < NUM_COLLECTION_ENTRIES; i++) { 177 final TestKey key = new TestKey(i * i); 178 179 final PersistableBundle innerBundle = new PersistableBundle(); 180 innerBundle.putInt(TEST_KEY, i); 181 final TestClass value = 182 new TestClass(i, TEST_INT_ARRAY, TEST_STRING_PREFIX + i, innerBundle); 183 184 sourceMap.put(key, value); 185 } 186 187 final PersistableBundle bundled = 188 PersistableBundleUtils.fromMap( 189 sourceMap, TestKey::toPersistableBundle, TestClass::toPersistableBundle); 190 final LinkedHashMap<TestKey, TestClass> resultList = 191 PersistableBundleUtils.toMap(bundled, TestKey::new, TestClass::new); 192 193 assertEquals(sourceMap, resultList); 194 } 195 196 @Test testByteArrayConversionLossless()197 public void testByteArrayConversionLossless() { 198 final byte[] byteArray = "testByteArrayConversionLossless".getBytes(); 199 200 PersistableBundle bundle = PersistableBundleUtils.fromByteArray(byteArray); 201 byte[] result = PersistableBundleUtils.toByteArray(bundle); 202 203 assertArrayEquals(byteArray, result); 204 } 205 206 @Test testIntegerConversionLossless()207 public void testIntegerConversionLossless() throws Exception { 208 final int testInt = 1; 209 final PersistableBundle integerBundle = 210 PersistableBundleUtils.INTEGER_SERIALIZER.toPersistableBundle(testInt); 211 final int result = 212 PersistableBundleUtils.INTEGER_DESERIALIZER.fromPersistableBundle(integerBundle); 213 214 assertEquals(testInt, result); 215 } 216 getTestBundle()217 private PersistableBundle getTestBundle() { 218 final PersistableBundle bundle = new PersistableBundle(); 219 220 bundle.putBoolean(TEST_KEY + "Boolean", true); 221 bundle.putBooleanArray(TEST_KEY + "BooleanArray", new boolean[] {true, false}); 222 bundle.putDouble(TEST_KEY + "Double", 0.1); 223 bundle.putDoubleArray(TEST_KEY + "DoubleArray", new double[] {0.1, 0.2, 0.3}); 224 bundle.putInt(TEST_KEY + "Int", 1); 225 bundle.putIntArray(TEST_KEY + "IntArray", new int[] {1, 2}); 226 bundle.putLong(TEST_KEY + "Long", 5L); 227 bundle.putLongArray(TEST_KEY + "LongArray", new long[] {0L, -1L, -2L}); 228 bundle.putString(TEST_KEY + "String", "TEST"); 229 bundle.putStringArray(TEST_KEY + "StringArray", new String[] {"foo", "bar", "bas"}); 230 bundle.putPersistableBundle( 231 TEST_KEY + "PersistableBundle", 232 new TestClass(1, TEST_INT_ARRAY, TEST_STRING_PREFIX, new PersistableBundle()) 233 .toPersistableBundle()); 234 235 return bundle; 236 } 237 238 @Test testMinimizeBundle()239 public void testMinimizeBundle() throws Exception { 240 final String[] minimizedKeys = 241 new String[] { 242 TEST_KEY + "Boolean", 243 TEST_KEY + "BooleanArray", 244 TEST_KEY + "Double", 245 TEST_KEY + "DoubleArray", 246 TEST_KEY + "Int", 247 TEST_KEY + "IntArray", 248 TEST_KEY + "Long", 249 TEST_KEY + "LongArray", 250 TEST_KEY + "String", 251 TEST_KEY + "StringArray", 252 TEST_KEY + "PersistableBundle" 253 }; 254 255 final PersistableBundle testBundle = getTestBundle(); 256 testBundle.putBoolean(TEST_KEY + "Boolean2", true); 257 258 final PersistableBundle minimized = 259 PersistableBundleUtils.minimizeBundle(testBundle, minimizedKeys); 260 261 // Verify that the minimized bundle is NOT the same in size OR values due to the extra 262 // Boolean2 key 263 assertFalse(PersistableBundleUtils.isEqual(testBundle, minimized)); 264 265 // Verify that removing the extra key from the source bundle results in equality. 266 testBundle.remove(TEST_KEY + "Boolean2"); 267 assertTrue(PersistableBundleUtils.isEqual(testBundle, minimized)); 268 } 269 270 @Test testToFromDiskStableBytes()271 public void testToFromDiskStableBytes() throws Exception { 272 final PersistableBundle testBundle = getTestBundle(); 273 final PersistableBundle result = 274 PersistableBundleUtils.fromDiskStableBytes( 275 PersistableBundleUtils.toDiskStableBytes(testBundle)); 276 assertTrue(PersistableBundleUtils.isEqual(testBundle, result)); 277 } 278 279 @Test testEquality_identical()280 public void testEquality_identical() throws Exception { 281 final PersistableBundle left = getTestBundle(); 282 final PersistableBundle right = getTestBundle(); 283 284 assertTrue(PersistableBundleUtils.isEqual(left, right)); 285 } 286 287 @Test testEquality_different()288 public void testEquality_different() throws Exception { 289 final PersistableBundle left = getTestBundle(); 290 final PersistableBundle right = getTestBundle(); 291 292 left.putBoolean(TEST_KEY + "Boolean2", true); 293 assertFalse(PersistableBundleUtils.isEqual(left, right)); 294 295 left.remove(TEST_KEY + "Boolean2"); 296 assertTrue(PersistableBundleUtils.isEqual(left, right)); 297 } 298 299 @Test testEquality_null()300 public void testEquality_null() throws Exception { 301 assertFalse(PersistableBundleUtils.isEqual(getTestBundle(), null)); 302 assertFalse(PersistableBundleUtils.isEqual(null, getTestBundle())); 303 assertTrue(PersistableBundleUtils.isEqual(null, null)); 304 } 305 } 306