/** * Copyright 2012 Facebook * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook; import android.os.Bundle; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; import com.facebook.internal.Utility; import junit.framework.Assert; import java.lang.reflect.Array; import java.util.*; public final class SharedPreferencesTokenCacheTests extends AndroidTestCase { private static final String BOOLEAN_KEY = "booleanKey"; private static final String BOOLEAN_ARRAY_KEY = "booleanArrayKey"; private static final String BYTE_KEY = "byteKey"; private static final String BYTE_ARRAY_KEY = "byteArrayKey"; private static final String SHORT_KEY = "shortKey"; private static final String SHORT_ARRAY_KEY = "shortArrayKey"; private static final String INT_KEY = "intKey"; private static final String INT_ARRAY_KEY = "intArrayKey"; private static final String LONG_KEY = "longKey"; private static final String LONG_ARRAY_KEY = "longArrayKey"; private static final String FLOAT_ARRAY_KEY = "floatKey"; private static final String FLOAT_KEY = "floatArrayKey"; private static final String DOUBLE_KEY = "doubleKey"; private static final String DOUBLE_ARRAY_KEY = "doubleArrayKey"; private static final String CHAR_KEY = "charKey"; private static final String CHAR_ARRAY_KEY = "charArrayKey"; private static final String STRING_KEY = "stringKey"; private static final String STRING_LIST_KEY = "stringListKey"; private static final String SERIALIZABLE_KEY = "serializableKey"; private static Random random = new Random((new Date()).getTime()); @SmallTest @MediumTest @LargeTest public void testAllTypes() { Bundle originalBundle = new Bundle(); putBoolean(BOOLEAN_KEY, originalBundle); putBooleanArray(BOOLEAN_ARRAY_KEY, originalBundle); putByte(BYTE_KEY, originalBundle); putByteArray(BYTE_ARRAY_KEY, originalBundle); putShort(SHORT_KEY, originalBundle); putShortArray(SHORT_ARRAY_KEY, originalBundle); putInt(INT_KEY, originalBundle); putIntArray(INT_ARRAY_KEY, originalBundle); putLong(LONG_KEY, originalBundle); putLongArray(LONG_ARRAY_KEY, originalBundle); putFloat(FLOAT_KEY, originalBundle); putFloatArray(FLOAT_ARRAY_KEY, originalBundle); putDouble(DOUBLE_KEY, originalBundle); putDoubleArray(DOUBLE_ARRAY_KEY, originalBundle); putChar(CHAR_KEY, originalBundle); putCharArray(CHAR_ARRAY_KEY, originalBundle); putString(STRING_KEY, originalBundle); putStringList(STRING_LIST_KEY, originalBundle); originalBundle.putSerializable(SERIALIZABLE_KEY, AccessTokenSource.FACEBOOK_APPLICATION_WEB); ensureApplicationContext(); SharedPreferencesTokenCachingStrategy cache = new SharedPreferencesTokenCachingStrategy(getContext()); cache.save(originalBundle); SharedPreferencesTokenCachingStrategy cache2 = new SharedPreferencesTokenCachingStrategy(getContext()); Bundle cachedBundle = cache2.load(); Assert.assertEquals(originalBundle.getBoolean(BOOLEAN_KEY), cachedBundle.getBoolean(BOOLEAN_KEY)); assertArrayEquals(originalBundle.getBooleanArray(BOOLEAN_ARRAY_KEY), cachedBundle.getBooleanArray(BOOLEAN_ARRAY_KEY)); Assert.assertEquals(originalBundle.getByte(BYTE_KEY), cachedBundle.getByte(BYTE_KEY)); assertArrayEquals(originalBundle.getByteArray(BYTE_ARRAY_KEY), cachedBundle.getByteArray(BYTE_ARRAY_KEY)); Assert.assertEquals(originalBundle.getShort(SHORT_KEY), cachedBundle.getShort(SHORT_KEY)); assertArrayEquals(originalBundle.getShortArray(SHORT_ARRAY_KEY), cachedBundle.getShortArray(SHORT_ARRAY_KEY)); Assert.assertEquals(originalBundle.getInt(INT_KEY), cachedBundle.getInt(INT_KEY)); assertArrayEquals(originalBundle.getIntArray(INT_ARRAY_KEY), cachedBundle.getIntArray(INT_ARRAY_KEY)); Assert.assertEquals(originalBundle.getLong(LONG_KEY), cachedBundle.getLong(LONG_KEY)); assertArrayEquals(originalBundle.getLongArray(LONG_ARRAY_KEY), cachedBundle.getLongArray(LONG_ARRAY_KEY)); Assert.assertEquals(originalBundle.getFloat(FLOAT_KEY), cachedBundle.getFloat(FLOAT_KEY)); assertArrayEquals(originalBundle.getFloatArray(FLOAT_ARRAY_KEY), cachedBundle.getFloatArray(FLOAT_ARRAY_KEY)); Assert.assertEquals(originalBundle.getDouble(DOUBLE_KEY), cachedBundle.getDouble(DOUBLE_KEY)); assertArrayEquals(originalBundle.getDoubleArray(DOUBLE_ARRAY_KEY), cachedBundle.getDoubleArray(DOUBLE_ARRAY_KEY)); Assert.assertEquals(originalBundle.getChar(CHAR_KEY), cachedBundle.getChar(CHAR_KEY)); assertArrayEquals(originalBundle.getCharArray(CHAR_ARRAY_KEY), cachedBundle.getCharArray(CHAR_ARRAY_KEY)); Assert.assertEquals(originalBundle.getString(STRING_KEY), cachedBundle.getString(STRING_KEY)); assertListEquals(originalBundle.getStringArrayList(STRING_LIST_KEY), cachedBundle.getStringArrayList( STRING_LIST_KEY)); Assert.assertEquals(originalBundle.getSerializable(SERIALIZABLE_KEY), cachedBundle.getSerializable(SERIALIZABLE_KEY)); } @SmallTest @MediumTest @LargeTest public void testMultipleCaches() { Bundle bundle1 = new Bundle(), bundle2 = new Bundle(); bundle1.putInt(INT_KEY, 10); bundle1.putString(STRING_KEY, "ABC"); bundle2.putInt(INT_KEY, 100); bundle2.putString(STRING_KEY, "xyz"); ensureApplicationContext(); SharedPreferencesTokenCachingStrategy cache1 = new SharedPreferencesTokenCachingStrategy(getContext()); SharedPreferencesTokenCachingStrategy cache2 = new SharedPreferencesTokenCachingStrategy(getContext(), "CustomCache"); cache1.save(bundle1); cache2.save(bundle2); // Get new references to make sure we are getting persisted data. // Reverse the cache references for fun. cache1 = new SharedPreferencesTokenCachingStrategy(getContext(), "CustomCache"); cache2 = new SharedPreferencesTokenCachingStrategy(getContext()); Bundle newBundle1 = cache1.load(), newBundle2 = cache2.load(); Assert.assertEquals(bundle2.getInt(INT_KEY), newBundle1.getInt(INT_KEY)); Assert.assertEquals(bundle2.getString(STRING_KEY), newBundle1.getString(STRING_KEY)); Assert.assertEquals(bundle1.getInt(INT_KEY), newBundle2.getInt(INT_KEY)); Assert.assertEquals(bundle1.getString(STRING_KEY), newBundle2.getString(STRING_KEY)); } @SmallTest @MediumTest @LargeTest public void testCacheRoundtrip() { ArrayList<String> permissions = Utility.arrayList("stream_publish", "go_outside_and_play"); String token = "AnImaginaryTokenValue"; Date later = TestUtils.nowPlusSeconds(60); Date earlier = TestUtils.nowPlusSeconds(-60); SharedPreferencesTokenCachingStrategy cache = new SharedPreferencesTokenCachingStrategy(getContext()); cache.clear(); Bundle bundle = new Bundle(); TokenCachingStrategy.putToken(bundle, token); TokenCachingStrategy.putExpirationDate(bundle, later); TokenCachingStrategy.putSource(bundle, AccessTokenSource.FACEBOOK_APPLICATION_NATIVE); TokenCachingStrategy.putLastRefreshDate(bundle, earlier); TokenCachingStrategy.putPermissions(bundle, permissions); cache.save(bundle); bundle = cache.load(); AccessToken accessToken = AccessToken.createFromCache(bundle); TestUtils.assertSamePermissions(permissions, accessToken); assertEquals(token, accessToken.getToken()); assertEquals(AccessTokenSource.FACEBOOK_APPLICATION_NATIVE, accessToken.getSource()); assertTrue(!accessToken.isInvalid()); Bundle cachedBundle = accessToken.toCacheBundle(); TestUtils.assertEqualContents(bundle, cachedBundle); } private static void assertArrayEquals(Object a1, Object a2) { Assert.assertNotNull(a1); Assert.assertNotNull(a2); Assert.assertEquals(a1.getClass(), a2.getClass()); Assert.assertTrue("Not an array", a1.getClass().isArray()); int length = Array.getLength(a1); Assert.assertEquals(length, Array.getLength(a2)); for (int i = 0; i < length; i++) { Object a1Value = Array.get(a1, i); Object a2Value = Array.get(a2, i); Assert.assertEquals(a1Value, a2Value); } } private static void assertListEquals(List<?> l1, List<?> l2) { Assert.assertNotNull(l1); Assert.assertNotNull(l2); Iterator<?> i1 = l1.iterator(), i2 = l2.iterator(); while (i1.hasNext() && i2.hasNext()) { Assert.assertEquals(i1.next(), i2.next()); } Assert.assertTrue("Lists not of the same length", !i1.hasNext()); Assert.assertTrue("Lists not of the same length", !i2.hasNext()); } private static void putInt(String key, Bundle bundle) { bundle.putInt(key, random.nextInt()); } private static void putIntArray(String key, Bundle bundle) { int length = random.nextInt(50); int[] array = new int[length]; for (int i = 0; i < length; i++) { array[i] = random.nextInt(); } bundle.putIntArray(key, array); } private static void putShort(String key, Bundle bundle) { bundle.putShort(key, (short)random.nextInt()); } private static void putShortArray(String key, Bundle bundle) { int length = random.nextInt(50); short[] array = new short[length]; for (int i = 0; i < length; i++) { array[i] = (short)random.nextInt(); } bundle.putShortArray(key, array); } private static void putByte(String key, Bundle bundle) { bundle.putByte(key, (byte)random.nextInt()); } private static void putByteArray(String key, Bundle bundle) { int length = random.nextInt(50); byte[] array = new byte[length]; random.nextBytes(array); bundle.putByteArray(key, array); } private static void putBoolean(String key, Bundle bundle) { bundle.putBoolean(key, random.nextBoolean()); } private static void putBooleanArray(String key, Bundle bundle) { int length = random.nextInt(50); boolean[] array = new boolean[length]; for (int i = 0; i < length; i++) { array[i] = random.nextBoolean(); } bundle.putBooleanArray(key, array); } private static void putLong(String key, Bundle bundle) { bundle.putLong(key, random.nextLong()); } private static void putLongArray(String key, Bundle bundle) { int length = random.nextInt(50); long[] array = new long[length]; for (int i = 0; i < length; i++) { array[i] = random.nextLong(); } bundle.putLongArray(key, array); } private static void putFloat(String key, Bundle bundle) { bundle.putFloat(key, random.nextFloat()); } private static void putFloatArray(String key, Bundle bundle) { int length = random.nextInt(50); float[] array = new float[length]; for (int i = 0; i < length; i++) { array[i] = random.nextFloat(); } bundle.putFloatArray(key, array); } private static void putDouble(String key, Bundle bundle) { bundle.putDouble(key, random.nextDouble()); } private static void putDoubleArray(String key, Bundle bundle) { int length = random.nextInt(50); double[] array = new double[length]; for (int i = 0; i < length; i++) { array[i] = random.nextDouble(); } bundle.putDoubleArray(key, array); } private static void putChar(String key, Bundle bundle) { bundle.putChar(key, getChar()); } private static void putCharArray(String key, Bundle bundle) { bundle.putCharArray(key, getCharArray()); } private static void putString(String key, Bundle bundle) { bundle.putString(key, new String(getCharArray())); } private static void putStringList(String key, Bundle bundle) { int length = random.nextInt(50); ArrayList<String> stringList = new ArrayList<String>(length); while (0 < length--) { if (length == 0) { stringList.add(null); } else { stringList.add(new String(getCharArray())); } } bundle.putStringArrayList(key, stringList); } private static char[] getCharArray() { int length = random.nextInt(50); char[] array = new char[length]; for (int i = 0; i < length; i++) { array[i] = getChar(); } return array; } private static char getChar() { return (char)random.nextInt(255); } private void ensureApplicationContext() { // Since the test case is not running on the UI thread, the applicationContext might // not be ready (i.e. it might be null). Wait for a bit to resolve this. long waitedFor = 0; try { // Don't hold up execution for too long. while (getContext().getApplicationContext() == null && waitedFor <= 2000) { Thread.sleep(50); waitedFor += 50; } } catch (InterruptedException e) { } } }