/*
* Copyright (C) 2014 SCVNGR, Inc. d/b/a LevelUp
*
* 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.scvngr.levelup.core.net;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.test.MoreAsserts;
import android.test.mock.MockContext;
import android.test.mock.MockPackageManager;
import android.test.suitebuilder.annotation.SmallTest;
import com.scvngr.levelup.core.R;
import com.scvngr.levelup.core.test.ParcelTestUtils;
import com.scvngr.levelup.core.test.SupportAndroidTestCase;
import com.scvngr.levelup.core.util.NullUtils;
import org.apache.http.protocol.HTTP;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* Tests {@link com.scvngr.levelup.core.net.LevelUpRequest}.
*/
public final class LevelUpRequestTest extends SupportAndroidTestCase {
@NonNull
private static final String TEST_VERSION = "v14";
@NonNull
private static final String TEST_ENDPOINT = "endpoint";
@NonNull
private Context mMockContext = new MyMockContext(new MyPackageManager(false));
@SuppressWarnings({ "null", "unused" })
@Override
protected void setUp() throws Exception {
super.setUp();
/*
* WHAT YOU SAY !! This is necessary due to a bug in the 2.3 testing framework.
* http://code.google.com/p/android/issues/detail?id=4244
*/
if (null == mMockContext) {
mMockContext = new MyMockContext(new MyPackageManager(false));
}
}
/**
* Tests {@link com.scvngr.levelup.core.net.LevelUpRequest} parceling without query parameters, a body, or an
* {@link com.scvngr.levelup.core.net.AccessTokenRetriever}.
*/
@SmallTest
public void testParcelable_basic() {
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null,
null);
ParcelTestUtils.assertParcelableRoundtrips(request);
}
/**
* Tests {@link com.scvngr.levelup.core.net.LevelUpRequest} parceling with query parameters, a body, and an
* {@link com.scvngr.levelup.core.net.AccessTokenRetriever}.
*/
@SmallTest
public void testParcelable_full() {
final HashMap<String, String> query = new HashMap<String, String>();
query.put("name", "test");
query.put("test", "hey");
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, query,
new MockRequestBody(), new MockAccessTokenRetriever());
ParcelTestUtils.assertParcelableRoundtrips(request);
}
/**
* Tests {@link com.scvngr.levelup.core.net.LevelUpRequest#getBody(android.content.Context)} when the user's access token
* should not be appended to the body.
*/
@SmallTest
public void testGetBody_empty() {
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null,
null);
assertEquals(null, request.getBody(mMockContext));
}
/**
* Tests {@link com.scvngr.levelup.core.net.LevelUpRequest#getAccessToken(android.content.Context)}.
*/
@SmallTest
public void testGetAccessToken() {
assertEquals(
"test_access_token", NullUtils.nonNullContract(new LevelUpRequest(mMockContext,
HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null, null,
new MockAccessTokenRetriever()).getAccessToken(mMockContext))
.getAccessToken());
assertEquals(null, new LevelUpRequest(mMockContext, HttpMethod.GET, TEST_VERSION,
TEST_ENDPOINT, null, null).getAccessToken(mMockContext));
}
@SmallTest
public void testHeaders_withoutAccessToken() {
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT, null,
null);
final HashMap<String, String> expectedHeaders =
new HashMap<String, String>(RequestUtils.getDefaultRequestHeaders(mMockContext));
expectedHeaders.put(HTTP.CONTENT_TYPE, RequestUtils.HEADER_CONTENT_TYPE_JSON);
expectedHeaders.put(LevelUpRequest.HEADER_LEVELUP_API_KEY, "test_api_key");
final Map<String, String> actualHeaders = request.getRequestHeaders(mMockContext);
assertFalse(actualHeaders.containsKey(LevelUpRequest.HEADER_AUTHORIZATION));
assertEquals(expectedHeaders, actualHeaders);
}
@SmallTest
public void testHeaders_withAccessToken() {
final MockAccessTokenRetriever retreiver = new MockAccessTokenRetriever();
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT,
null, null, retreiver);
final HashMap<String, String> expectedHeaders =
new HashMap<String, String>(RequestUtils.getDefaultRequestHeaders(mMockContext));
expectedHeaders.put(HTTP.CONTENT_TYPE, RequestUtils.HEADER_CONTENT_TYPE_JSON);
expectedHeaders.put(LevelUpRequest.HEADER_LEVELUP_API_KEY, "test_api_key");
expectedHeaders
.put(LevelUpRequest.HEADER_AUTHORIZATION, String.format(Locale.US,
LevelUpRequest.AUTH_TOKEN_TYPE_FORMAT,
NullUtils.nonNullContract(retreiver.getAccessToken(mMockContext))
.getAccessToken()));
final Map<String, String> actualHeaders = request.getRequestHeaders(mMockContext);
assertEquals(expectedHeaders, actualHeaders);
}
@SmallTest
public void testGetFullUrl() {
final String endpoint = "users/1";
final String match =
String.format(
Locale.US,
"%s://%s/%s/%s", getContext().getString(R.string.levelup_api_scheme),
getContext().getString(R.string.levelup_api_authority),
LevelUpRequest.API_VERSION_CODE_V14, endpoint);
assertEquals(match, LevelUpRequest.getFullUrl(getContext(),
LevelUpRequest.API_VERSION_CODE_V14, endpoint));
}
@SmallTest
public void testGetBody_null() {
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT,
null, null);
assertNull(request.getBody(mMockContext));
}
@SmallTest
public void testRequestBody_fixtureEquals() {
assertEquals(new MockRequestBody(), new MockRequestBody());
}
@SmallTest
public void testGetBody_fromRequestBody() {
final RequestBody body = new MockRequestBody();
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT, null,
body);
assertEquals(MockRequestBody.BODY_FIXTURE, request.getBody(mMockContext));
}
@SmallTest
public void testRequestBody_contentType() {
final RequestBody body = new MockRequestBody();
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT, null,
body);
final Map<String, String> requestHeaders = request.getRequestHeaders(mMockContext);
assertTrue(requestHeaders.containsKey(HTTP.CONTENT_TYPE));
assertEquals(MockRequestBody.FIXTURE_CONTENT_TYPE, requestHeaders.get(HTTP.CONTENT_TYPE));
}
@SmallTest
public void testRequestBody_contentLength() {
final RequestBody body = new MockRequestBody();
final LevelUpRequest request =
new LevelUpRequest(mMockContext, HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT, null,
body);
final int expectedLength = body.getContentLength();
assertTrue(0 < expectedLength);
final Map<String, String> requestHeaders = request.getRequestHeaders(mMockContext);
assertTrue(requestHeaders.containsKey(HTTP.CONTENT_LEN));
assertEquals(String.valueOf(expectedLength), requestHeaders.get(HTTP.CONTENT_LEN));
assertEquals(expectedLength, request.getBodyLength(mMockContext));
}
@SmallTest
public void testEqualsAndHashCode() {
LevelUpRequest request1 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null,
null);
LevelUpRequest request2 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null,
null);
final Map<String, String> hash = new HashMap<String, String>();
hash.put("test", "test");
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, true);
// Test equalities
request1 =
new LevelUpRequest(getContext(), HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT,
null, null);
request2 =
new LevelUpRequest(getContext(), HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT,
null, null);
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, true);
request1 = new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION + "version",
TEST_ENDPOINT, null, null);
request2 = new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION + "version",
TEST_ENDPOINT, null, null);
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, true);
request1 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT
+ "endpoint", null, null);
request2 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT
+ "endpoint", null, null);
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, true);
request1 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, hash,
null);
request2 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, hash,
null);
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, true);
request1 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null,
new MockRequestBody());
request2 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null,
new MockRequestBody());
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, true);
// Test differences
request1 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null,
null);
request2 =
new LevelUpRequest(getContext(), HttpMethod.POST, TEST_VERSION, TEST_ENDPOINT,
null, null);
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, false);
request2 = new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION + "version",
TEST_ENDPOINT, null, null);
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, false);
request2 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT
+ "endpoint", null, null);
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, false);
request2 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, hash,
null);
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, false);
request2 =
new LevelUpRequest(getContext(), HttpMethod.GET, TEST_VERSION, TEST_ENDPOINT, null,
new MockRequestBody());
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, false);
request2 = null;
MoreAsserts.checkEqualsAndHashCodeMethods(request1, request2, false);
}
/**
* Mock Context to return a fake PackageManager.
*/
private final class MyMockContext extends MockContext {
@NonNull
private final MyPackageManager mMgr;
/**
* Constructor.
*
* @param mgr the fake package manager to return
*/
public MyMockContext(@NonNull final MyPackageManager mgr) {
mMgr = mgr;
}
@Override
public PackageManager getPackageManager() {
return mMgr;
}
@Override
public ApplicationInfo getApplicationInfo() {
final ApplicationInfo info = new ApplicationInfo();
info.name = "LevelUp-Core-Fallback";
return info;
}
@Override
public String getPackageName() {
return null;
}
@Override
public SharedPreferences getSharedPreferences(@Nullable final String name, final int mode) {
throw new UnsupportedOperationException();
}
@Override
public Context getApplicationContext() {
return this;
}
@Override
public Resources getResources() {
return getContext().getResources();
}
}
/**
* Fakes the PackageManager API for getting package data.
*/
private static final class MyPackageManager extends MockPackageManager {
private final boolean mThrowException;
/**
* Constructor.
*
* @param throwException if true, {@link #getPackageInfo(String, int)} will throw a
* {@link android.content.pm.PackageManager.NameNotFoundException} when called.
*/
public MyPackageManager(final boolean throwException) {
mThrowException = throwException;
}
@Override
public PackageInfo getPackageInfo(@Nullable final String packageName, final int flags)
throws NameNotFoundException {
if (mThrowException) {
throw new NameNotFoundException();
}
final PackageInfo info = new PackageInfo();
info.versionName = "2.3.8";
info.applicationInfo = new ApplicationInfo();
info.applicationInfo.name = "LevelUp-Core";
return info;
}
}
}