Extract some test helper methods for easier reuse

Test: ran unit test
Change-Id: I6873d0b174942eef20cf44945b7e7869770827a7
diff --git a/tests/src/com/android/contacts/database/SimContactDaoTests.java b/tests/src/com/android/contacts/database/SimContactDaoTests.java
index 080662a..69a7e1f 100644
--- a/tests/src/com/android/contacts/database/SimContactDaoTests.java
+++ b/tests/src/com/android/contacts/database/SimContactDaoTests.java
@@ -20,8 +20,6 @@
 import android.content.Context;
 import android.content.OperationApplicationException;
 import android.database.Cursor;
-import android.database.CursorWrapper;
-import android.database.DatabaseUtils;
 import android.os.RemoteException;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Email;
@@ -43,13 +41,12 @@
 import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.common.test.mocks.MockContentProvider;
 import com.android.contacts.tests.AccountsTestHelper;
+import com.android.contacts.tests.ContactsMatchers;
 import com.android.contacts.tests.SimContactsTestHelper;
+import com.android.contacts.tests.StringableCursor;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -68,6 +65,10 @@
 import java.util.Set;
 
 import static android.os.Build.VERSION_CODES;
+import static com.android.contacts.tests.ContactsMatchers.DataCursor.hasEmail;
+import static com.android.contacts.tests.ContactsMatchers.DataCursor.hasName;
+import static com.android.contacts.tests.ContactsMatchers.DataCursor.hasPhone;
+import static com.android.contacts.tests.ContactsMatchers.isSimContactWithNameAndPhone;
 import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.equalTo;
 import static org.junit.Assert.assertThat;
@@ -127,19 +128,19 @@
             ), mAccount);
 
             Cursor cursor = queryContactWithName("Test One");
-            assertThat(cursor, hasCount(2));
+            assertThat(cursor, ContactsMatchers.hasCount(2));
             assertThat(cursor, hasName("Test One"));
             assertThat(cursor, hasPhone("15095550101"));
             cursor.close();
 
             cursor = queryContactWithName("Test Two");
-            assertThat(cursor, hasCount(2));
+            assertThat(cursor, ContactsMatchers.hasCount(2));
             assertThat(cursor, hasName("Test Two"));
             assertThat(cursor, hasPhone("15095550102"));
             cursor.close();
 
             cursor = queryContactWithName("Test Three");
-            assertThat(cursor, hasCount(4));
+            assertThat(cursor, ContactsMatchers.hasCount(4));
             assertThat(cursor, hasName("Test Three"));
             assertThat(cursor, hasPhone("15095550103"));
             assertThat(cursor, allOf(hasEmail("user@example.com"), hasEmail("user2@example.com")));
@@ -156,7 +157,7 @@
 
             Cursor cursor = queryAllDataInAccount();
 
-            assertThat(cursor, hasCount(1));
+            assertThat(cursor, ContactsMatchers.hasCount(1));
             assertThat(cursor, hasName("Test importJustName"));
             cursor.close();
         }
@@ -171,7 +172,7 @@
 
             Cursor cursor = queryAllDataInAccount();
 
-            assertThat(cursor, hasCount(1));
+            assertThat(cursor, ContactsMatchers.hasCount(1));
             assertThat(cursor, hasPhone("15095550111"));
             cursor.close();
         }
@@ -190,11 +191,11 @@
             ), mAccount);
 
             final Cursor contactsCursor = queryAllRawContactsInAccount();
-            assertThat(contactsCursor, hasCount(1));
+            assertThat(contactsCursor, ContactsMatchers.hasCount(1));
             contactsCursor.close();
 
             final Cursor dataCursor = queryAllDataInAccount();
-            assertThat(dataCursor, hasCount(1));
+            assertThat(dataCursor, ContactsMatchers.hasCount(1));
 
             dataCursor.close();
         }
@@ -218,12 +219,12 @@
             sut.importContacts(contacts, mAccount);
 
             final Cursor contactsCursor = queryAllRawContactsInAccount();
-            assertThat(contactsCursor, hasCount(MAX_SIM_CONTACTS));
+            assertThat(contactsCursor, ContactsMatchers.hasCount(MAX_SIM_CONTACTS));
             contactsCursor.close();
 
             final Cursor dataCursor = queryAllDataInAccount();
             // Each contact has one data row for each of name, phone and email
-            assertThat(dataCursor, hasCount(MAX_SIM_CONTACTS * 3));
+            assertThat(dataCursor, ContactsMatchers.hasCount(MAX_SIM_CONTACTS * 3));
 
             dataCursor.close();
         }
@@ -740,126 +741,6 @@
         }
     }
 
-    private static Matcher<SimContact> isSimContactWithNameAndPhone(final String name,
-            final String phone) {
-        return new BaseMatcher<SimContact>() {
-            @Override
-            public boolean matches(Object o) {
-                if (!(o instanceof SimContact))  return false;
-
-                SimContact other = (SimContact) o;
-
-                return name.equals(other.getName())
-                        && phone.equals(other.getPhone());
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("SimContact with name=" + name + " and phone=" +
-                        phone);
-            }
-        };
-    }
-
-    private static Matcher<Cursor> hasCount(final int count) {
-        return new BaseMatcher<Cursor>() {
-            @Override
-            public boolean matches(Object o) {
-                if (!(o instanceof Cursor)) return false;
-                return ((Cursor)o).getCount() == count;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("Cursor with " + count + " rows");
-            }
-        };
-    }
-
-    private static Matcher<Cursor> hasMimeType(String type) {
-        return hasValueForColumn(Data.MIMETYPE, type);
-    }
-
-    private static Matcher<Cursor> hasValueForColumn(final String column, final String value) {
-        return new BaseMatcher<Cursor>() {
-
-            @Override
-            public boolean matches(Object o) {
-                if (!(o instanceof Cursor)) return false;
-                final Cursor cursor = (Cursor)o;
-
-                final int index = cursor.getColumnIndexOrThrow(column);
-                return value.equals(cursor.getString(index));
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("Cursor with " + column + "=" + value);
-            }
-        };
-    }
-
-    private static Matcher<Cursor> hasRowMatching(final Matcher<Cursor> rowMatcher) {
-        return new BaseMatcher<Cursor>() {
-            @Override
-            public boolean matches(Object o) {
-                if (!(o instanceof Cursor)) return false;
-                final Cursor cursor = (Cursor)o;
-
-                cursor.moveToPosition(-1);
-                while (cursor.moveToNext()) {
-                    if (rowMatcher.matches(cursor)) return true;
-                }
-
-                return false;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("Cursor with row matching ");
-                rowMatcher.describeTo(description);
-            }
-        };
-    }
-
-    private static Matcher<Cursor> hasName(final String name) {
-        return hasRowMatching(allOf(
-                hasMimeType(StructuredName.CONTENT_ITEM_TYPE),
-                hasValueForColumn(
-                        StructuredName.DISPLAY_NAME, name)));
-    }
-
-    private static Matcher<Cursor> hasPhone(final String phone) {
-        return hasRowMatching(allOf(
-                hasMimeType(Phone.CONTENT_ITEM_TYPE),
-                hasValueForColumn(
-                        Phone.NUMBER, phone)));
-    }
-
-    private static Matcher<Cursor> hasEmail(final String email) {
-        return hasRowMatching(allOf(
-                hasMimeType(Email.CONTENT_ITEM_TYPE),
-                hasValueForColumn(
-                        Email.ADDRESS, email)));
-    }
-
-    static class StringableCursor extends CursorWrapper {
-        public StringableCursor(Cursor cursor) {
-            super(cursor);
-        }
-
-        @Override
-        public String toString() {
-            final Cursor wrapped = getWrappedCursor();
-
-            if (wrapped.getCount() == 0) {
-                return "Empty Cursor";
-            }
-
-            return DatabaseUtils.dumpCursorToString(wrapped);
-        }
-    }
-
     private static String randomPhone() {
         return String.format(Locale.US, "1%s55501%02d",
                 AREA_CODES[sRandom.nextInt(AREA_CODES.length)],
diff --git a/tests/src/com/android/contacts/tests/ContactsMatchers.java b/tests/src/com/android/contacts/tests/ContactsMatchers.java
new file mode 100644
index 0000000..a3a08de
--- /dev/null
+++ b/tests/src/com/android/contacts/tests/ContactsMatchers.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 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.contacts.tests;
+
+import android.database.Cursor;
+import android.provider.ContactsContract;
+
+import com.android.contacts.model.SimContact;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.Matchers.allOf;
+
+
+/**
+ * Has useful {@link org.hamcrest.Matchers}s for the Contacts app
+ */
+public class ContactsMatchers {
+
+    private ContactsMatchers() {
+    }
+
+    /**
+     * Matchers for {@link Cursor}s returned by queries to
+     * {@link android.provider.ContactsContract.Data#CONTENT_URI}
+     */
+    public static class DataCursor {
+
+        public static Matcher<Cursor> hasMimeType(String type) {
+            return hasValueForColumn(ContactsContract.Data.MIMETYPE, type);
+        }
+
+        public static Matcher<Cursor> hasName(final String name) {
+            return hasRowMatching(allOf(
+                    hasMimeType(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE),
+                    hasValueForColumn(
+                            ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)));
+        }
+
+        public static Matcher<Cursor> hasPhone(final String phone) {
+            return hasRowMatching(allOf(
+                    hasMimeType(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE),
+                    hasValueForColumn(
+                            ContactsContract.CommonDataKinds.Phone.NUMBER, phone)));
+        }
+
+        public static Matcher<Cursor> hasEmail(final String email) {
+            return hasRowMatching(allOf(
+                    hasMimeType(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE),
+                    hasValueForColumn(
+                            ContactsContract.CommonDataKinds.Email.ADDRESS, email)));
+        }
+    }
+
+    public static Matcher<Cursor> hasCount(final int count) {
+        return new BaseMatcher<Cursor>() {
+            @Override
+            public boolean matches(Object o) {
+                if (!(o instanceof Cursor)) return false;
+                return ((Cursor)o).getCount() == count;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("Cursor with " + count + " rows");
+            }
+        };
+    }
+
+    public static Matcher<Cursor> hasValueForColumn(final String column, final String value) {
+        return new BaseMatcher<Cursor>() {
+
+            @Override
+            public boolean matches(Object o) {
+                if (!(o instanceof Cursor)) return false;
+                final Cursor cursor = (Cursor)o;
+
+                final int index = cursor.getColumnIndexOrThrow(column);
+                return value.equals(cursor.getString(index));
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("Cursor with " + column + "=" + value);
+            }
+        };
+    }
+
+    public static Matcher<Cursor> hasRowMatching(final Matcher<Cursor> rowMatcher) {
+        return new BaseMatcher<Cursor>() {
+            @Override
+            public boolean matches(Object o) {
+                if (!(o instanceof Cursor)) return false;
+                final Cursor cursor = (Cursor)o;
+
+                cursor.moveToPosition(-1);
+                while (cursor.moveToNext()) {
+                    if (rowMatcher.matches(cursor)) return true;
+                }
+
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("Cursor with row matching ");
+                rowMatcher.describeTo(description);
+            }
+        };
+    }
+
+    public static Matcher<SimContact> isSimContactWithNameAndPhone(final String name,
+            final String phone) {
+        return new BaseMatcher<SimContact>() {
+            @Override
+            public boolean matches(Object o) {
+                if (!(o instanceof SimContact))  return false;
+
+                SimContact other = (SimContact) o;
+
+                return name.equals(other.getName())
+                        && phone.equals(other.getPhone());
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("SimContact with name=" + name + " and phone=" +
+                        phone);
+            }
+        };
+    }
+}
diff --git a/tests/src/com/android/contacts/tests/StringableCursor.java b/tests/src/com/android/contacts/tests/StringableCursor.java
new file mode 100644
index 0000000..dbe3fca
--- /dev/null
+++ b/tests/src/com/android/contacts/tests/StringableCursor.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 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.contacts.tests;
+
+import android.database.Cursor;
+import android.database.CursorWrapper;
+import android.database.DatabaseUtils;
+
+/**
+ * Wrapper around a cursor with a custom toString that dumps the entire cursor data
+ *
+ * This is for providing more useful info during debugging and testing.
+ */
+public class StringableCursor extends CursorWrapper {
+    public StringableCursor(Cursor cursor) {
+        super(cursor);
+    }
+
+    @Override
+    public String toString() {
+        final Cursor wrapped = getWrappedCursor();
+
+        if (wrapped.getCount() == 0) {
+            return "Empty Cursor";
+        }
+
+        return DatabaseUtils.dumpCursorToString(wrapped);
+    }
+}