/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
* copy, modify, and distribute this software in source code or binary form for use
* in connection with the web services and APIs provided by Facebook.
*
* As with any software that integrates with the Facebook platform, your use of
* this software is subject to the Facebook Developer Principles and Policies
* [http://developers.facebook.com/policy/]. This copyright notice shall be
* included in all copies or substantial portions of the software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.facebook;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.facebook.internal.Utility;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.robolectric.RuntimeEnvironment;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.support.membermodification.MemberModifier.stub;
@PrepareForTest( {
AccessTokenCache.class,
FacebookSdk.class,
LegacyTokenHelper.class,
Utility.class})
public class AccessTokenCacheTest extends FacebookPowerMockTestCase {
private final String TOKEN_STRING = "A token of my esteem";
private final String USER_ID = "1000";
private final List<String> PERMISSIONS = Arrays.asList("walk", "chew gum");
private final Date EXPIRES = new Date(2025, 5, 3);
private final Date LAST_REFRESH = new Date(2023, 8, 15);
private final String APP_ID = "1234";
private SharedPreferences sharedPreferences;
@Mock private LegacyTokenHelper cachingStrategy;
private AccessTokenCache.SharedPreferencesTokenCachingStrategyFactory
cachingStrategyFactory;
@Before
public void before() throws Exception {
mockStatic(FacebookSdk.class);
sharedPreferences = RuntimeEnvironment.application.getSharedPreferences(
AccessTokenManager.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
sharedPreferences.edit().clear().commit();
cachingStrategyFactory = mock(
AccessTokenCache.SharedPreferencesTokenCachingStrategyFactory.class);
when(cachingStrategyFactory.create()).thenReturn(cachingStrategy);
stub(PowerMockito.method(Utility.class, "awaitGetGraphMeRequestWithCache")).toReturn(
new JSONObject().put("id", "1000"));
}
@Test
public void testLoadReturnsFalseIfNoCachedToken() {
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
AccessToken accessToken = cache.load();
assertNull(accessToken);
PowerMockito.verifyZeroInteractions(cachingStrategy);
}
@Test
public void testLoadReturnsFalseIfNoCachedOrLegacyToken() {
when(FacebookSdk.isLegacyTokenUpgradeSupported()).thenReturn(true);
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
AccessToken accessToken = cache.load();
assertNull(accessToken);
}
@Test
public void testLoadReturnsFalseIfEmptyCachedTokenAndDoesNotCheckLegacy() {
JSONObject jsonObject = new JSONObject();
sharedPreferences.edit().putString(AccessTokenCache.CACHED_ACCESS_TOKEN_KEY,
jsonObject.toString()).commit();
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
AccessToken accessToken = cache.load();
assertNull(accessToken);
verifyZeroInteractions(cachingStrategy);
}
@Test
public void testLoadReturnsFalseIfNoCachedTokenAndEmptyLegacyToken() {
when(FacebookSdk.isLegacyTokenUpgradeSupported()).thenReturn(true);
when(cachingStrategy.load()).thenReturn(new Bundle());
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
AccessToken accessToken = cache.load();
assertNull(accessToken);
}
@Test
public void testLoadValidCachedToken() throws JSONException {
AccessToken accessToken = createAccessToken();
JSONObject jsonObject = accessToken.toJSONObject();
sharedPreferences.edit().putString(AccessTokenCache.CACHED_ACCESS_TOKEN_KEY,
jsonObject.toString()).commit();
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
AccessToken loadedAccessToken = cache.load();
assertNotNull(loadedAccessToken);
assertEquals(accessToken, loadedAccessToken);
}
@Test
public void testLoadSetsCurrentTokenIfNoCachedTokenButValidLegacyToken() {
when(FacebookSdk.isLegacyTokenUpgradeSupported()).thenReturn(true);
AccessToken accessToken = createAccessToken();
when(cachingStrategy.load()).thenReturn(
AccessTokenTestHelper.toLegacyCacheBundle(accessToken));
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
AccessToken loadedAccessToken = cache.load();
assertNotNull(loadedAccessToken);
assertEquals(accessToken, loadedAccessToken);
}
@Test
public void testLoadSavesTokenWhenUpgradingFromLegacyToken() throws JSONException {
when(FacebookSdk.isLegacyTokenUpgradeSupported()).thenReturn(true);
AccessToken accessToken = createAccessToken();
when(cachingStrategy.load()).thenReturn(
AccessTokenTestHelper.toLegacyCacheBundle(accessToken));
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
cache.load();
assertTrue(sharedPreferences.contains(AccessTokenCache.CACHED_ACCESS_TOKEN_KEY));
AccessToken savedAccessToken = AccessToken.createFromJSONObject(
new JSONObject(sharedPreferences.getString(
AccessTokenCache.CACHED_ACCESS_TOKEN_KEY, null)));
assertEquals(accessToken, savedAccessToken);
}
@Test
public void testLoadClearsLegacyCacheWhenUpgradingFromLegacyToken() {
when(FacebookSdk.isLegacyTokenUpgradeSupported()).thenReturn(true);
AccessToken accessToken = createAccessToken();
when(cachingStrategy.load()).thenReturn(
AccessTokenTestHelper.toLegacyCacheBundle(accessToken));
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
cache.load();
verify(cachingStrategy, times(1)).clear();
}
@Test
public void testSaveRequiresToken() {
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
try {
cache.save(null);
fail();
} catch (NullPointerException exception) {
}
}
@Test
public void testSaveWritesToCacheIfToken() throws JSONException {
AccessToken accessToken = createAccessToken();
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
cache.save(accessToken);
verify(cachingStrategy, never()).save(any(Bundle.class));
assertTrue(sharedPreferences.contains(AccessTokenCache.CACHED_ACCESS_TOKEN_KEY));
AccessToken savedAccessToken = AccessToken.createFromJSONObject(
new JSONObject(sharedPreferences.getString(
AccessTokenCache.CACHED_ACCESS_TOKEN_KEY, null)));
assertEquals(accessToken, savedAccessToken);
}
@Test
public void testClearCacheClearsCache() {
AccessToken accessToken = createAccessToken();
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
cache.save(accessToken);
cache.clear();
assertFalse(sharedPreferences.contains(AccessTokenCache.CACHED_ACCESS_TOKEN_KEY));
verify(cachingStrategy, never()).clear();
}
@Test
public void testClearCacheClearsLegacyCache() {
when(FacebookSdk.isLegacyTokenUpgradeSupported()).thenReturn(true);
AccessToken accessToken = createAccessToken();
AccessTokenCache cache = new AccessTokenCache(sharedPreferences, cachingStrategyFactory);
cache.save(accessToken);
cache.clear();
assertFalse(sharedPreferences.contains(AccessTokenCache.CACHED_ACCESS_TOKEN_KEY));
verify(cachingStrategy, times(1)).clear();
}
private AccessToken createAccessToken() {
return createAccessToken(TOKEN_STRING, USER_ID);
}
private AccessToken createAccessToken(String tokenString, String userId) {
return new AccessToken(
tokenString,
APP_ID,
userId,
PERMISSIONS,
null,
AccessTokenSource.WEB_VIEW,
EXPIRES,
LAST_REFRESH);
}
}