/* * Copyright (C) 2020 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.net.vcn.util; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.os.PersistableBundle; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; @RunWith(AndroidJUnit4.class) @SmallTest public class PersistableBundleUtilsTest { private static final String TEST_KEY = "testKey"; private static final String TEST_STRING_PREFIX = "testString"; private static final int[] TEST_INT_ARRAY = new int[] {0, 1, 2, 3, 4}; private static final int NUM_COLLECTION_ENTRIES = 10; private static class TestKey { private static final String TEST_INTEGER_KEY = "mTestInteger"; // Purposely colliding with keys of test class to ensure namespacing private final int mTestInteger; TestKey(int testInteger) { mTestInteger = testInteger; } TestKey(PersistableBundle in) { mTestInteger = in.getInt(TEST_INTEGER_KEY); } public PersistableBundle toPersistableBundle() { final PersistableBundle result = new PersistableBundle(); result.putInt(TEST_INTEGER_KEY, mTestInteger); return result; } @Override public int hashCode() { return Objects.hash(mTestInteger); } @Override public boolean equals(Object o) { if (!(o instanceof TestKey)) { return false; } final TestKey other = (TestKey) o; return mTestInteger == other.mTestInteger; } } private static class TestClass { private static final String TEST_INTEGER_KEY = "mTestInteger"; private final int mTestInteger; private static final String TEST_INT_ARRAY_KEY = "mTestIntArray"; private final int[] mTestIntArray; private static final String TEST_STRING_KEY = "mTestString"; private final String mTestString; private static final String TEST_PERSISTABLE_BUNDLE_KEY = "mTestPersistableBundle"; private final PersistableBundle mTestPersistableBundle; TestClass( int testInteger, int[] testIntArray, String testString, PersistableBundle testPersistableBundle) { mTestInteger = testInteger; mTestIntArray = testIntArray; mTestString = testString; mTestPersistableBundle = testPersistableBundle; } TestClass(PersistableBundle in) { mTestInteger = in.getInt(TEST_INTEGER_KEY); mTestIntArray = in.getIntArray(TEST_INT_ARRAY_KEY); mTestString = in.getString(TEST_STRING_KEY); mTestPersistableBundle = in.getPersistableBundle(TEST_PERSISTABLE_BUNDLE_KEY); } public PersistableBundle toPersistableBundle() { final PersistableBundle result = new PersistableBundle(); result.putInt(TEST_INTEGER_KEY, mTestInteger); result.putIntArray(TEST_INT_ARRAY_KEY, mTestIntArray); result.putString(TEST_STRING_KEY, mTestString); result.putPersistableBundle(TEST_PERSISTABLE_BUNDLE_KEY, mTestPersistableBundle); return result; } @Override public int hashCode() { return Objects.hash( mTestInteger, Arrays.hashCode(mTestIntArray), mTestString, mTestPersistableBundle); } @Override public boolean equals(Object o) { if (!(o instanceof TestClass)) { return false; } final TestClass other = (TestClass) o; // TODO: Add a proper equals() to PersistableBundle. But in the meantime, force // TODO: unparcelling in order to allow test comparison. if (mTestPersistableBundle.size() != other.mTestPersistableBundle.size()) { return false; } return mTestInteger == other.mTestInteger && Arrays.equals(mTestIntArray, other.mTestIntArray) && mTestString.equals(other.mTestString) && mTestPersistableBundle.kindofEquals(other.mTestPersistableBundle); } } @Test public void testListConversionLossless() throws Exception { final List sourceList = new ArrayList<>(); for (int i = 0; i < NUM_COLLECTION_ENTRIES; i++) { final PersistableBundle innerBundle = new PersistableBundle(); innerBundle.putInt(TEST_KEY, i); sourceList.add(new TestClass(i, TEST_INT_ARRAY, TEST_STRING_PREFIX + i, innerBundle)); } final PersistableBundle bundled = PersistableBundleUtils.fromList(sourceList, TestClass::toPersistableBundle); final List resultList = PersistableBundleUtils.toList(bundled, TestClass::new); assertEquals(sourceList, resultList); } @Test public void testMapConversionLossless() throws Exception { final LinkedHashMap sourceMap = new LinkedHashMap<>(); for (int i = 0; i < NUM_COLLECTION_ENTRIES; i++) { final TestKey key = new TestKey(i * i); final PersistableBundle innerBundle = new PersistableBundle(); innerBundle.putInt(TEST_KEY, i); final TestClass value = new TestClass(i, TEST_INT_ARRAY, TEST_STRING_PREFIX + i, innerBundle); sourceMap.put(key, value); } final PersistableBundle bundled = PersistableBundleUtils.fromMap( sourceMap, TestKey::toPersistableBundle, TestClass::toPersistableBundle); final LinkedHashMap resultList = PersistableBundleUtils.toMap(bundled, TestKey::new, TestClass::new); assertEquals(sourceMap, resultList); } @Test public void testByteArrayConversionLossless() { final byte[] byteArray = "testByteArrayConversionLossless".getBytes(); PersistableBundle bundle = PersistableBundleUtils.fromByteArray(byteArray); byte[] result = PersistableBundleUtils.toByteArray(bundle); assertArrayEquals(byteArray, result); } @Test public void testIntegerConversionLossless() throws Exception { final int testInt = 1; final PersistableBundle integerBundle = PersistableBundleUtils.INTEGER_SERIALIZER.toPersistableBundle(testInt); final int result = PersistableBundleUtils.INTEGER_DESERIALIZER.fromPersistableBundle(integerBundle); assertEquals(testInt, result); } private PersistableBundle getTestBundle() { final PersistableBundle bundle = new PersistableBundle(); bundle.putBoolean(TEST_KEY + "Boolean", true); bundle.putBooleanArray(TEST_KEY + "BooleanArray", new boolean[] {true, false}); bundle.putDouble(TEST_KEY + "Double", 0.1); bundle.putDoubleArray(TEST_KEY + "DoubleArray", new double[] {0.1, 0.2, 0.3}); bundle.putInt(TEST_KEY + "Int", 1); bundle.putIntArray(TEST_KEY + "IntArray", new int[] {1, 2}); bundle.putLong(TEST_KEY + "Long", 5L); bundle.putLongArray(TEST_KEY + "LongArray", new long[] {0L, -1L, -2L}); bundle.putString(TEST_KEY + "String", "TEST"); bundle.putStringArray(TEST_KEY + "StringArray", new String[] {"foo", "bar", "bas"}); bundle.putPersistableBundle( TEST_KEY + "PersistableBundle", new TestClass(1, TEST_INT_ARRAY, TEST_STRING_PREFIX, new PersistableBundle()) .toPersistableBundle()); return bundle; } @Test public void testMinimizeBundle() throws Exception { final String[] minimizedKeys = new String[] { TEST_KEY + "Boolean", TEST_KEY + "BooleanArray", TEST_KEY + "Double", TEST_KEY + "DoubleArray", TEST_KEY + "Int", TEST_KEY + "IntArray", TEST_KEY + "Long", TEST_KEY + "LongArray", TEST_KEY + "String", TEST_KEY + "StringArray", TEST_KEY + "PersistableBundle" }; final PersistableBundle testBundle = getTestBundle(); testBundle.putBoolean(TEST_KEY + "Boolean2", true); final PersistableBundle minimized = PersistableBundleUtils.minimizeBundle(testBundle, minimizedKeys); // Verify that the minimized bundle is NOT the same in size OR values due to the extra // Boolean2 key assertFalse(PersistableBundleUtils.isEqual(testBundle, minimized)); // Verify that removing the extra key from the source bundle results in equality. testBundle.remove(TEST_KEY + "Boolean2"); assertTrue(PersistableBundleUtils.isEqual(testBundle, minimized)); } @Test public void testToFromDiskStableBytes() throws Exception { final PersistableBundle testBundle = getTestBundle(); final PersistableBundle result = PersistableBundleUtils.fromDiskStableBytes( PersistableBundleUtils.toDiskStableBytes(testBundle)); assertTrue(PersistableBundleUtils.isEqual(testBundle, result)); } @Test public void testEquality_identical() throws Exception { final PersistableBundle left = getTestBundle(); final PersistableBundle right = getTestBundle(); assertTrue(PersistableBundleUtils.isEqual(left, right)); } @Test public void testEquality_different() throws Exception { final PersistableBundle left = getTestBundle(); final PersistableBundle right = getTestBundle(); left.putBoolean(TEST_KEY + "Boolean2", true); assertFalse(PersistableBundleUtils.isEqual(left, right)); left.remove(TEST_KEY + "Boolean2"); assertTrue(PersistableBundleUtils.isEqual(left, right)); } @Test public void testEquality_null() throws Exception { assertFalse(PersistableBundleUtils.isEqual(getTestBundle(), null)); assertFalse(PersistableBundleUtils.isEqual(null, getTestBundle())); assertTrue(PersistableBundleUtils.isEqual(null, null)); } }