/* * 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.os.Build; import android.support.annotation.NonNull; 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.SupportAndroidTestCase; import com.scvngr.levelup.core.util.CoreLibConstants; import com.scvngr.levelup.core.util.NullUtils; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; import java.util.Locale; import java.util.Map; /** * Tests {@link com.scvngr.levelup.core.net.RequestUtils}. */ public final class RequestUtilsTest extends SupportAndroidTestCase { /** * Eventually non-null; initialized in {@link #setUp()}. */ @SuppressWarnings("null") @NonNull private Context mMockContext; @Override protected void setUp() throws Exception { super.setUp(); mMockContext = new RequestUtilsMockContext(getContext(), new RequestUtilsMockPackageManager()); } /** * Tests {@link com.scvngr.levelup.core.net.RequestUtils#getDefaultRequestHeaders(android.content.Context)} when a * {@link android.content.pm.PackageManager.NameNotFoundException} is not thrown. */ @SmallTest public void testGetDefaultRequestHeaders() { final Map<String, String> headers = RequestUtils.getDefaultRequestHeaders(mMockContext); assertTrue("Device model header is present", headers.containsKey("X-Device-Model")); assertEquals("Accept header is set for JSON", // RequestUtils.HEADER_CONTENT_TYPE_JSON, headers.get(RequestUtils.HEADER_ACCEPT)); assertEquals("User-Agent header matches RequestUtils.getUserAgent()", RequestUtils.getUserAgent(mMockContext), headers.get("User-Agent")); } @SmallTest public void testGetUserAgent() { assertTrue(RequestUtils.getUserAgent(mMockContext).contains( "com.example.testapp/2.3.8" + getDeviceSpecificUserAgentString())); assertTrue(RequestUtils.getUserAgent(mMockContext).contains( "LevelUpSdk/" + CoreLibConstants.SDK_VERSION)); /* * Ensure we're not using properties that come back null in our User-Agent (like * applicationInfo.name). This is a mocked context so it's not an ideal test, but there's * not a great way to unit-test real-world values. */ assertFalse( "User-Agent should not have 'null' for any of its properties", RequestUtils.getUserAgent(mMockContext).contains( "null")); } /** * Test {@link com.scvngr.levelup.core.net.RequestUtils#addApiKeyToRequestQueryParams}. */ @SmallTest public void testAddApiKeyToRequestQueryParams() { final Map<String, String> expected = new HashMap<String, String>(); final Map<String, String> params = new HashMap<String, String>(); final Context context = NullUtils.nonNullContract(getContext()); expected.put(RequestUtils.PARAM_API_KEY, context.getString(R.string.levelup_api_key)); RequestUtils.addApiKeyToRequestQueryParams(context, params); assertEquals(expected.toString(), params.toString()); } /** * Test {@link com.scvngr.levelup.core.net.RequestUtils#addApiKeyToRequestBody}. * * @throws org.json.JSONException from {@link org.json.JSONObject#put} */ @SmallTest public void testAddApiKeyToRequestBody() throws JSONException { final JSONObject object = new JSONObject(); final JSONObject expected = new JSONObject(); final Context context = NullUtils.nonNullContract(getContext()); expected.put(RequestUtils.PARAM_API_KEY, context.getString(R.string.levelup_api_key)); RequestUtils.addApiKeyToRequestBody(context, object); assertEquals(expected.toString(), object.toString()); } /** * Test {@link com.scvngr.levelup.core.net.RequestUtils#addDeviceIdToRequestBody}. * * @throws org.json.JSONException from {@link org.json.JSONObject#getString} */ @SmallTest public void testAddDeviceIdToRequestBody() throws JSONException { final JSONObject object = new JSONObject(); final Context context = NullUtils.nonNullContract(getContext()); RequestUtils.addDeviceIdToRequestBody(context, object); assertTrue(object.has(RequestUtils.PARAM_DEVICE_IDENTIFIER)); assertEquals(RequestUtils.getDeviceId(context), object.getString(RequestUtils.PARAM_DEVICE_IDENTIFIER)); } /** * Helper method to get the device specific portion of the user agent screen. * * @return device specific part of the user agent string */ private static String getDeviceSpecificUserAgentString() { return String.format(Locale.US, " (Linux; U; Android %s; %s/%s; %s)", Build.VERSION.RELEASE, Build.BRAND, Build.PRODUCT, Locale.getDefault().toString()); } /** * Mock Context to return a fake PackageManager. */ public static final class RequestUtilsMockContext extends MockContext { @NonNull private final RequestUtilsMockPackageManager mMgr; @NonNull private final Context mContext; /** * Constructor. * * @param context the context. * @param mgr the fake package manager to return */ public RequestUtilsMockContext(@NonNull final Context context, @NonNull final RequestUtilsMockPackageManager mgr) { mContext = context; 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(final String name, final int mode) { throw new UnsupportedOperationException(); } @Override public Context getApplicationContext() { return mContext.getApplicationContext(); } @Override public Resources getResources() { return mContext.getResources(); } } /** * Fakes the PackageManager API for getting package data. */ public static final class RequestUtilsMockPackageManager extends MockPackageManager { @Override public PackageInfo getPackageInfo(final String packageName, final int flags) throws NameNotFoundException { final PackageInfo info = new PackageInfo(); info.versionName = "2.3.8"; info.applicationInfo = new ApplicationInfo(); info.applicationInfo.name = null; // This is the case for many apps. info.applicationInfo.packageName = "com.example.testapp"; return info; } } }