NPE fix in NameComparator when null strings are provided by the
caller. b/12894779

This is the integration of an Exchange fix from Motorola. As part
of this fix, unit tests have been introduced to verify that we
are experiencing the correct behavior. Writing these unit tests
required some factoring/unwrapped to make the code easier to test.

Change-Id: I3fe8278c56fb13e2e43f32c3eeba1cbe01ea3b8b
(cherry picked from commit 6fd3b6c35d930ee045cb6cfe3d6770d450b7b523)
diff --git a/src/com/android/exchange/provider/ExchangeDirectoryProvider.java b/src/com/android/exchange/provider/ExchangeDirectoryProvider.java
index 6eea16e..b5d274a 100644
--- a/src/com/android/exchange/provider/ExchangeDirectoryProvider.java
+++ b/src/com/android/exchange/provider/ExchangeDirectoryProvider.java
@@ -565,17 +565,20 @@
      *      preserved both between contacts with the same name and for
      *      multiple results within a given contact
      */
-    private static class GalSortKey {
+    protected static class GalSortKey {
         final String sortName;
-        final int    id;
+        final int id;
 
-        public GalSortKey(String sortName, int id) {
+        public GalSortKey(final String sortName, final int id) {
             this.sortName = sortName;
             this.id = id;
         }
     }
 
-    private static class NameComparator implements Comparator<GalSortKey> {
+    /**
+     * The Comparator that is used by ExchangeDirectoryProvider
+     */
+    protected static class NameComparator implements Comparator<GalSortKey> {
         private final Collator collator;
 
         public NameComparator() {
@@ -585,15 +588,19 @@
         }
 
         @Override
-        public int compare(GalSortKey lhs, GalSortKey rhs) {
-            final int res = collator.compare(lhs.sortName, rhs.sortName);
-            if (res != 0) {
-                return res;
+        public int compare(final GalSortKey lhs, final GalSortKey rhs) {
+            final int res;
+            if (lhs.sortName != null && rhs.sortName != null) {
+                res = collator.compare(lhs.sortName, rhs.sortName);
+                if (res != 0) {
+                    return res;
+                }
             }
-            if (lhs.id != rhs.id) {
-                return lhs.id > rhs.id ? 1 : -1;
+            // Either the names compared equally or one was not provided, use the id to compare.
+            if (lhs.id == rhs.id) {
+                return 0;
             }
-            return 0;
+            return lhs.id > rhs.id ? 1 : -1;
         }
     }
 
diff --git a/tests/src/com/android/exchange/provider/ExchangeDirectoryProviderTests.java b/tests/src/com/android/exchange/provider/ExchangeDirectoryProviderTests.java
index e4bd791..6e6f688 100644
--- a/tests/src/com/android/exchange/provider/ExchangeDirectoryProviderTests.java
+++ b/tests/src/com/android/exchange/provider/ExchangeDirectoryProviderTests.java
@@ -143,4 +143,110 @@
         assertEquals((Long)acctFoo.mId, provider.mAccountIdMap.get("foo@android.com"));
         assertEquals((Long)acctBar.mId, provider.mAccountIdMap.get("bar@android.com"));
     }
+
+    /**
+     * The purpose of these next tests are to test the ExchangeDirectoryProvider. NameComparator comparison function
+     * and not the Collator class. This means that we can test only with Western strings.
+     * Note that there is a loose assumption that IDs always exist. If this is a valid
+     * assumption, we should enforce it in the ExchangeDirectoryProvider.GalSortKey class or in the compare function.
+     */
+    public void testNameComparatorEqualsStringLhsIdGreater() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey("A", 2);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey("A", 1);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, 1);
+    }
+
+    public void testNameComparatorEqualsStringRhsIdGreater() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey("A", 1);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey("A", 2);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, -1);
+    }
+
+    public void testNameComparatorEqualsEverythingEqual() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey("A", 1);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey("A", 1);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, 0);
+    }
+
+    public void testNameComparatorLhsGreaterString() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey("B", 1);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey("A", 2);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, 1);
+    }
+
+    public void testNameComparatorRhsGreaterString() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey("A", 1);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey("B", 2);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, -1);
+    }
+
+    public void testNameComparatorLhsNoStringLhsWins() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey(null, 2);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey("A", 1);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, 1);
+    }
+
+    public void testNameComparatorLhsNoStringRhsWins() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey(null, 1);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey("A", 2);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, -1);
+    }
+
+    public void testNameComparatorRhsNoStringLhsWins() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey("A", 2);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey(null, 1);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, 1);
+    }
+
+    public void testNameComparatorRhsNoStringRhsWins() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey("A", 1);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey(null, 2);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, -1);
+    }
+
+    public void testNameComparatorNoStringsLhsWins() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey(null, 2);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey(null, 1);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, 1);
+    }
+
+    public void testNameComparatorNoStringsRhsWins() {
+        final ExchangeDirectoryProvider.GalSortKey lhs = new ExchangeDirectoryProvider.GalSortKey(null, 1);
+        final ExchangeDirectoryProvider.GalSortKey rhs = new ExchangeDirectoryProvider.GalSortKey(null, 2);
+
+        final ExchangeDirectoryProvider. NameComparator comparator = new ExchangeDirectoryProvider. NameComparator();
+        final int ret = comparator.compare(lhs, rhs);
+        assertEquals(ret, -1);
+    }
+
 }