From 1611d0baed730df920b0685d3031a4bc98c6f225 Mon Sep 17 00:00:00 2001 From: Ben Komalo Date: Mon, 25 Apr 2011 15:46:50 -0400 Subject: [PATCH] Make ImapStore tests use mocks where possible Change-Id: I2a1d5e7d3cc3b105a24a5fc29772bcd4a0308ad3 --- src/com/android/email/VendorPolicyLoader.java | 2 - .../android/email/mail/store/ImapStore.java | 9 +- .../android/email/MockSharedPreferences.java | 151 ++++++++++++++++++ .../email/mail/store/ImapStoreUnitTests.java | 47 +++++- 4 files changed, 199 insertions(+), 10 deletions(-) create mode 100644 tests/src/com/android/email/MockSharedPreferences.java diff --git a/src/com/android/email/VendorPolicyLoader.java b/src/com/android/email/VendorPolicyLoader.java index f4e3613c9..8f97afea8 100644 --- a/src/com/android/email/VendorPolicyLoader.java +++ b/src/com/android/email/VendorPolicyLoader.java @@ -26,8 +26,6 @@ import android.os.Bundle; import android.util.Log; import java.lang.reflect.Method; -import java.net.URI; -import java.net.URISyntaxException; /** * A bridge class to the email vendor policy apk. diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java index 0c2c68423..757a26ee6 100644 --- a/src/com/android/email/mail/store/ImapStore.java +++ b/src/com/android/email/mail/store/ImapStore.java @@ -42,6 +42,7 @@ import com.android.emailcommon.provider.EmailContent.HostAuth; import com.android.emailcommon.service.EmailServiceProxy; import com.android.emailcommon.utility.Utility; import com.beetstra.jutf7.CharsetProvider; +import com.google.common.annotations.VisibleForTesting; import android.content.Context; import android.os.Build; @@ -99,7 +100,7 @@ public class ImapStore extends Store { private String mPassword; private String mLoginPhrase; private String mIdPhrase = null; - private static String sImapId = null; + @VisibleForTesting static String sImapId = null; /*package*/ String mPathPrefix; /*package*/ String mPathSeparator; @@ -118,7 +119,7 @@ public class ImapStore extends Store { * requests. This cache lets us make sure we always reuse, if possible, for a given * folder name. */ - private HashMap mFolderCache = new HashMap(); + private final HashMap mFolderCache = new HashMap(); /** * Next tag to use. All connections associated to the same ImapStore instance share the same @@ -219,7 +220,7 @@ public class ImapStore extends Store { * @param capabilities a list of the capabilities from the server * @return a String for use in an IMAP ID message. */ - /* package */ static String getImapId(Context context, String userName, String host, + @VisibleForTesting static String getImapId(Context context, String userName, String host, String capabilities) { // The first section is global to all IMAP connections, and generates the fixed // values in any IMAP ID message @@ -280,7 +281,7 @@ public class ImapStore extends Store { * @param networkOperator TelephonyManager.getNetworkOperatorName() * @return the static (never changes) portion of the IMAP ID */ - /* package */ static String makeCommonImapId(String packageName, String version, + @VisibleForTesting static String makeCommonImapId(String packageName, String version, String codeName, String model, String id, String vendor, String networkOperator) { // Before building up IMAP ID string, pre-filter the input strings for "legal" chars diff --git a/tests/src/com/android/email/MockSharedPreferences.java b/tests/src/com/android/email/MockSharedPreferences.java new file mode 100644 index 000000000..025e06d91 --- /dev/null +++ b/tests/src/com/android/email/MockSharedPreferences.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2011 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 com.android.email; + +import com.google.android.collect.Maps; + +import android.content.SharedPreferences; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +/** + * A programmable mock content provider. + */ +public class MockSharedPreferences implements SharedPreferences, SharedPreferences.Editor { + + private HashMap mValues = Maps.newHashMap(); + private HashMap mTempValues = Maps.newHashMap(); + + @SuppressWarnings("unchecked") + public Editor edit() { + mTempValues = (HashMap) mValues.clone(); + return this; + } + + public boolean contains(String key) { + return mValues.containsKey(key); + } + + public Map getAll() { + return new HashMap(mValues); + } + + public boolean getBoolean(String key, boolean defValue) { + if (mValues.containsKey(key)) { + return ((Boolean)mValues.get(key)).booleanValue(); + } + return defValue; + } + + public float getFloat(String key, float defValue) { + if (mValues.containsKey(key)) { + return ((Float)mValues.get(key)).floatValue(); + } + return defValue; + } + + public int getInt(String key, int defValue) { + if (mValues.containsKey(key)) { + return ((Integer)mValues.get(key)).intValue(); + } + return defValue; + } + + public long getLong(String key, long defValue) { + if (mValues.containsKey(key)) { + return ((Long)mValues.get(key)).longValue(); + } + return defValue; + } + + public String getString(String key, String defValue) { + if (mValues.containsKey(key)) + return (String)mValues.get(key); + return defValue; + } + + @SuppressWarnings("unchecked") + public Set getStringSet(String key, Set defValues) { + if (mValues.containsKey(key)) { + return (Set) mValues.get(key); + } + return defValues; + } + + public void registerOnSharedPreferenceChangeListener( + OnSharedPreferenceChangeListener listener) { + throw new UnsupportedOperationException(); + } + + public void unregisterOnSharedPreferenceChangeListener( + OnSharedPreferenceChangeListener listener) { + throw new UnsupportedOperationException(); + } + + public Editor putBoolean(String key, boolean value) { + mTempValues.put(key, Boolean.valueOf(value)); + return this; + } + + public Editor putFloat(String key, float value) { + mTempValues.put(key, value); + return this; + } + + public Editor putInt(String key, int value) { + mTempValues.put(key, value); + return this; + } + + public Editor putLong(String key, long value) { + mTempValues.put(key, value); + return this; + } + + public Editor putString(String key, String value) { + mTempValues.put(key, value); + return this; + } + + public Editor putStringSet(String key, Set values) { + mTempValues.put(key, values); + return this; + } + + public Editor remove(String key) { + mTempValues.remove(key); + return this; + } + + public Editor clear() { + mTempValues.clear(); + return this; + } + + @SuppressWarnings("unchecked") + public boolean commit() { + mValues = (HashMap) mTempValues.clone(); + return true; + } + + public void apply() { + commit(); + } +} diff --git a/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java b/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java index d6b6aa066..1a74c443b 100644 --- a/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java +++ b/tests/src/com/android/email/mail/store/ImapStoreUnitTests.java @@ -16,6 +16,8 @@ package com.android.email.mail.store; +import com.android.email.DBTestHelper; +import com.android.email.MockSharedPreferences; import com.android.email.MockVendorPolicy; import com.android.email.VendorPolicyLoader; import com.android.email.mail.Transport; @@ -48,6 +50,10 @@ import com.android.emailcommon.utility.Utility; import org.apache.commons.io.IOUtils; import android.content.Context; +import android.content.ContextWrapper; +import android.content.SharedPreferences; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Build; import android.os.Bundle; import android.test.InstrumentationTestCase; import android.test.MoreAsserts; @@ -96,16 +102,49 @@ public class ImapStoreUnitTests extends InstrumentationTestCase { private Folder mCopyToFolder; private Message[] mCopyMessages; + /** + * A wrapper to provide a wrapper to a Context which has already been mocked. + * This allows additional methods to delegate to the original, real context, in cases + * where the mocked behavior is insufficient. + */ + private class SecondaryMockContext extends ContextWrapper { + private final Context mUnderlying; + + public SecondaryMockContext(Context mocked, Context underlying) { + super(mocked); + mUnderlying = underlying; + } + + // TODO: eliminate the need for these method. + @Override + public Context createPackageContext(String packageName, int flags) + throws NameNotFoundException { + return mUnderlying.createPackageContext(packageName, flags); + } + + @Override + public SharedPreferences getSharedPreferences(String name, int mode) { + return new MockSharedPreferences(); + } + } + /** * Setup code. We generate a lightweight ImapStore and ImapStore.ImapFolder. */ @Override protected void setUp() throws Exception { super.setUp(); - // TODO: this should really use a mock context. - mTestContext = getInstrumentation().getTargetContext(); - // Use the target's (i.e. the Email application) context - TempDirectory.setTempDirectory(getInstrumentation().getTargetContext()); + Context realContext = getInstrumentation().getTargetContext(); + ImapStore.sImapId = ImapStore.makeCommonImapId(realContext.getPackageName(), + Build.VERSION.RELEASE, Build.VERSION.CODENAME, + Build.MODEL, Build.ID, Build.MANUFACTURER, + "FakeNetworkOperator"); + mTestContext = new SecondaryMockContext( + DBTestHelper.ProviderContextSetupHelper.getProviderContext(realContext), + realContext); + MockVendorPolicy.inject(mTestContext); + + TempDirectory.setTempDirectory(mTestContext); // These are needed so we can get at the inner classes HostAuth testAuth = new HostAuth();