diff --git a/src/com/android/email/Preferences.java b/src/com/android/email/Preferences.java index 71b18e834..f10e27365 100644 --- a/src/com/android/email/Preferences.java +++ b/src/com/android/email/Preferences.java @@ -23,6 +23,7 @@ import android.content.SharedPreferences; import android.net.Uri; import android.util.Log; +import java.util.HashMap; import java.util.UUID; public class Preferences { @@ -44,6 +45,7 @@ public class Preferences { private static final String AUTO_ADVANCE_DIRECTION = "autoAdvance"; private static final String TEXT_ZOOM = "textZoom"; private static final String BACKGROUND_ATTACHMENTS = "backgroundAttachments"; + private static final String MESSAGE_NOTIFICATION_TABLE = "messageNotificationTable"; public static final int AUTO_ADVANCE_NEWER = 0; public static final int AUTO_ADVANCE_OLDER = 1; @@ -249,6 +251,55 @@ public class Preferences { mSharedPreferences.edit().putBoolean(BACKGROUND_ATTACHMENTS, allowed).apply(); } + public HashMap getMessageNotificationTable() { + HashMap table = new HashMap(); + // The table is encoded as a string with the following format: + // K:V1,V2;K:V1,V2;... + // Where 'K' is the table key and 'V1' and 'V2' are the array values associated with the key + // Multiple key/value pairs are separated from one another by a ';'. + String preference = mSharedPreferences.getString(MESSAGE_NOTIFICATION_TABLE, ""); + String[] entries = preference.split(";"); + for (String entry : entries) { + try { + String hash[] = entry.split(":"); + if (hash.length != 2) continue; + String stringValues[] = hash[1].split(","); + if (stringValues.length != 2) continue; + long key = Long.parseLong(hash[0]); + long[] value = new long[2]; + value[0] = Long.parseLong(stringValues[0]); + value[1] = Long.parseLong(stringValues[1]); + table.put(key, value); + } catch (NumberFormatException e) { + Log.w(Logging.LOG_TAG, "notification table preference corrupt"); + continue; + } + } + return table; + } + + /** + * Sets the message notification table. + * @throws IllegalArgumentException if the given table is null or any of the value arrays do + * not have exactly 2 elements. + */ + public void setMessageNotificationTable(HashMap notificationTable) { + StringBuffer sb = new StringBuffer(); + boolean first = true; + if (notificationTable == null) throw new IllegalArgumentException("table cannot be null"); + for (Long key : notificationTable.keySet()) { + if (!first) { + sb.append(';'); + } + long[] value = notificationTable.get(key); + if (value == null || value.length != 2) { + throw new IllegalArgumentException("value array must contain 2 elements"); + } + sb.append(key).append(':').append(value[0]).append(',').append(value[1]); + first = false; + } + mSharedPreferences.edit().putString(MESSAGE_NOTIFICATION_TABLE, sb.toString()).apply(); + } public void save() { } diff --git a/tests/src/com/android/email/DBTestHelper.java b/tests/src/com/android/email/DBTestHelper.java index 964973a16..de8a1cbb3 100644 --- a/tests/src/com/android/email/DBTestHelper.java +++ b/tests/src/com/android/email/DBTestHelper.java @@ -26,6 +26,7 @@ import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; +import android.content.SharedPreferences; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.database.Cursor; @@ -200,6 +201,11 @@ public final class DBTestHelper { public Theme getTheme() { return mRealContext.getTheme(); } + + @Override + public SharedPreferences getSharedPreferences(String name, int mode) { + return new MockSharedPreferences(); + } } /** diff --git a/tests/src/com/android/email/PreferencesUnitTests.java b/tests/src/com/android/email/PreferencesUnitTests.java index c9129f799..5ab24c401 100644 --- a/tests/src/com/android/email/PreferencesUnitTests.java +++ b/tests/src/com/android/email/PreferencesUnitTests.java @@ -16,13 +16,16 @@ package com.android.email; +import android.content.Context; import android.net.Uri; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; +import java.util.HashMap; + /** * This is a series of unit tests for the Preferences class. - * + * * Technically these are functional because they use the underlying preferences framework. It * would be a really good idea if we could inject our own underlying preferences storage, to better * test cases like zero accounts behavior (right now, we have to allow for any number of accounts @@ -32,66 +35,204 @@ import android.test.suitebuilder.annotation.SmallTest; public class PreferencesUnitTests extends AndroidTestCase { private Preferences mPreferences; - - private Account mAccount; - + private Context mMockContext; + @Override protected void setUp() throws Exception { super.setUp(); - - mPreferences = Preferences.getPreferences(getContext()); + mMockContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext(mContext); + mPreferences = Preferences.getPreferences(mMockContext); } - /** - * Delete any dummy accounts we set up for this test - */ - @Override - protected void tearDown() throws Exception { - super.tearDown(); - - if (mAccount != null && mPreferences != null) { - mAccount.delete(mPreferences); + /** Just because this does exist anywhere else */ + private void assertEquals(long[] expected, long[] actual) { + assertNotNull(actual); + assertEquals(expected.length, actual.length); + for (int i = expected.length - 1; i >= 0; i--) { + if (expected[i] != actual[i]) { + fail("expected array element[" + i + "]:<" + + expected[i] + "> but was:<" + actual[i] + '>'); + } + } + } + private void assertEquals(HashMap expected, HashMap actual) { + assertNotNull(actual); + assertEquals(expected.size(), actual.size()); + for (Long key : expected.keySet()) { + assertTrue(actual.containsKey(key)); + long[] expectedArray = expected.get(key); + long[] actualArray = actual.get(key); + assertEquals(expectedArray, actualArray); } } - /** * Test the new getAccountByContentUri() API. This should return null if no * accounts are configured, or the Uri doesn't match, and it should return a desired account * otherwise. - * + * * TODO: Not actually testing the no-accounts case */ public void testGetAccountByContentUri() { // Create a dummy account - createTestAccount(); - + Account account = new Account(mMockContext); + account.save(mPreferences); + // test sunny-day lookup by Uri - Uri testAccountUri = mAccount.getContentUri(); + Uri testAccountUri = account.getContentUri(); Account lookup = mPreferences.getAccountByContentUri(testAccountUri); - assertEquals(mAccount, lookup); - + assertEquals(account, lookup); + // now make it a bogus Uri - bad scheme, good path, good UUID - testAccountUri = Uri.parse("bogus://accounts/" + mAccount.getUuid()); + testAccountUri = Uri.parse("bogus://accounts/" + account.getUuid()); lookup = mPreferences.getAccountByContentUri(testAccountUri); assertNull(lookup); - + // now make it a bogus Uri - good scheme, bad path, good UUID - testAccountUri = Uri.parse("content://bogus/" + mAccount.getUuid()); + testAccountUri = Uri.parse("content://bogus/" + account.getUuid()); lookup = mPreferences.getAccountByContentUri(testAccountUri); assertNull(lookup); - + // now make it a bogus Uri - good scheme/path, bad UUID - testAccountUri = Uri.parse("content://accounts/" + mAccount.getUuid() + "-bogus"); + testAccountUri = Uri.parse("content://accounts/" + account.getUuid() + "-bogus"); lookup = mPreferences.getAccountByContentUri(testAccountUri); assertNull(lookup); } - - /** - * Create a dummy account with minimal fields - */ - private void createTestAccount() { - mAccount = new Account(getContext()); - mAccount.save(mPreferences); + + public void testSetMessageNotificationTable() { + HashMap testTable = new HashMap(); + String testString; + + // One account + testTable.clear(); + testTable.put(5L, new long[] { 2L, 3L }); + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "value_unset").apply(); + mPreferences.setMessageNotificationTable(testTable); + testString = mPreferences.mSharedPreferences.getString("messageNotificationTable", null); + assertEquals("5:2,3", testString); + + // Multiple accounts + // NOTE: This assumes a very specific order in the hash map and is fragile; if the hash + // map is ever changed, this may break unexpectedly. + testTable.clear(); + testTable.put(5L, new long[] { 2L, 3L }); + testTable.put(3L, new long[] { 1L, 8L }); + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "value_unset").apply(); + mPreferences.setMessageNotificationTable(testTable); + testString = mPreferences.mSharedPreferences.getString("messageNotificationTable", null); + assertEquals("5:2,3;3:1,8", testString); + + // Wrong number of elements in the array + // NOTE: This assumes a very specific order in the hash map and is fragile; if the hash + // map is ever changed, this may break unexpectedly. + testTable.clear(); + testTable.put(5L, new long[] { 2L, 3L, 8L }); // too many + testTable.put(3L, new long[] { 1L, 8L }); + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "value_unset_1").apply(); + try { + mPreferences.setMessageNotificationTable(testTable); + fail("expected an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + testString = mPreferences.mSharedPreferences.getString("messageNotificationTable", null); + assertEquals("value_unset_1", testString); + testTable.clear(); + testTable.put(5L, new long[] { 2L }); // too few + testTable.put(3L, new long[] { 1L, 8L }); + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "value_unset_2").apply(); + try { + mPreferences.setMessageNotificationTable(testTable); + fail("expected an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + testString = mPreferences.mSharedPreferences.getString("messageNotificationTable", null); + assertEquals("value_unset_2", testString); + + // Nulls in strange places + testTable.clear(); + testTable.put(5L, null); // no array + testTable.put(3L, new long[] { 1L, 8L }); + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "value_unset_3").apply(); + try { + mPreferences.setMessageNotificationTable(testTable); + fail("expected an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + testString = mPreferences.mSharedPreferences.getString("messageNotificationTable", null); + assertEquals("value_unset_3", testString); + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "value_unset_4").apply(); + try { + mPreferences.setMessageNotificationTable(null); // no table + fail("expected an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + testString = mPreferences.mSharedPreferences.getString("messageNotificationTable", null); + assertEquals("value_unset_4", testString); + } + + public void testGetMessageNotificationTable() { + HashMap testTable; + HashMap expectedTable = new HashMap(); + + // Test initial condition + assertFalse(mPreferences.mSharedPreferences.contains("messageNotificationTable")); + + // One account + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "5:2,3").apply(); + testTable = mPreferences.getMessageNotificationTable(); + expectedTable.clear(); + expectedTable.put(5L, new long[] { 2L, 3L }); + assertEquals(expectedTable, testTable); + + // Multiple accounts + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "5:2,3;3:1,8;6:5,3").apply(); + testTable = mPreferences.getMessageNotificationTable(); + expectedTable.clear(); + expectedTable.put(5L, new long[] { 2L, 3L }); + expectedTable.put(3L, new long[] { 1L, 8L }); + expectedTable.put(6L, new long[] { 5L, 3L }); + assertEquals(expectedTable, testTable); + + // Empty account + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "5:2,3;").apply(); + testTable = mPreferences.getMessageNotificationTable(); + expectedTable.clear(); + expectedTable.put(5L, new long[] { 2L, 3L }); + assertEquals(expectedTable, testTable); + + // Empty fields + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "5:2,3;3:").apply(); + testTable = mPreferences.getMessageNotificationTable(); + expectedTable.clear(); + expectedTable.put(5L, new long[] { 2L, 3L }); + assertEquals(expectedTable, testTable); + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "5:2,3;3:1,").apply(); + testTable = mPreferences.getMessageNotificationTable(); + expectedTable.clear(); + expectedTable.put(5L, new long[] { 2L, 3L }); + assertEquals(expectedTable, testTable); + + // Garbage + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "blahblahblah").apply(); + testTable = mPreferences.getMessageNotificationTable(); + expectedTable.clear(); + assertEquals(expectedTable, testTable); // empty table + mPreferences.mSharedPreferences.edit() + .putString("messageNotificationTable", "5:2,3;blahblahblah").apply(); + testTable = mPreferences.getMessageNotificationTable(); + expectedTable.clear(); + expectedTable.put(5L, new long[] { 2L, 3L }); + assertEquals(expectedTable, testTable); } - }