new file mode 100644
--- /dev/null
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/db/BrowserProviderDomainHashTest.java
@@ -0,0 +1,210 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.gecko.db;
+
+import android.content.ContentProviderClient;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.RemoteException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mozilla.gecko.background.testhelpers.TestRunner;
+import org.mozilla.gecko.db.BrowserContract.Bookmarks;
+import org.mozilla.gecko.db.BrowserContract.History;
+import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
+
+import java.util.UUID;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+@RunWith(TestRunner.class)
+public class BrowserProviderDomainHashTest extends BrowserProviderHistoryVisitsTestBase {
+
+ private Uri bookmarksTestUri;
+
+ private ContentProviderClient bookmarksClient;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ bookmarksClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.BOOKMARKS_CONTENT_URI);
+
+ bookmarksTestUri = testUri(BrowserContract.Bookmarks.CONTENT_URI);
+ }
+
+ @After
+ public void tearDown() {
+ bookmarksClient.release();
+
+ super.tearDown();
+ }
+
+ /**
+ * Iterate over a cursor (from history/bookmarks/combined/etc), that contains
+ * a total of four URLs (one www.mozilla.org URL, one mozilla.org URL, one foobar.mozilla.org one mozilla.de URL), and
+ * verify that appropriate domain hashes have been generated.
+ * <p>
+ * The supplied cursor will be closed once testing is complete.
+ */
+ private void testFourItemCursor(final Cursor cursor,
+ final String urlColumnTitle,
+ final String domainFullHashColumnTitle,
+ final String domainStrippedHashColumnTitle,
+ final String domainBaseHashColumnTitle) {
+ try {
+ assertEquals(4, cursor.getCount());
+
+ final int urlColumn = cursor.getColumnIndexOrThrow(urlColumnTitle);
+ final int domainFullHashColumn = cursor.getColumnIndexOrThrow(domainFullHashColumnTitle);
+ final int domainStrippedHashColumn = cursor.getColumnIndexOrThrow(domainStrippedHashColumnTitle);
+ final int domainBaseHashColumn = cursor.getColumnIndexOrThrow(domainBaseHashColumnTitle);
+
+ // Store the first domain for later checking: 1 of the 3 mozilla.org URLs has a different
+ // subdomain, so it's stripped domain will be different - we need to know which
+ // hash we've stored to correctly verify later hashes:
+ String firstMozillaOrgURL = null;
+ int mozillaOrgFullDomainHash = -1;
+ int mozillaOrgStrippedDomainHash = -1;
+ int mozillaOrgBaseDomainHash = -1;
+
+ int mozillaDeFullDomainHash = -1;
+ int mozillaDeStrippedDomainHash = -1;
+ int mozillaDeBaseDomainHash = -1;
+
+ while (cursor.moveToNext()) {
+ final String url = cursor.getString(urlColumn);
+ final int domainFullHash = cursor.getInt(domainFullHashColumn);
+ final int domainStrippedHash = cursor.getInt(domainStrippedHashColumn);
+ final int domainBaseHash = cursor.getInt(domainBaseHashColumn);
+
+ if (url.contains("mozilla.org")) {
+ if (firstMozillaOrgURL == null) {
+ firstMozillaOrgURL = url;
+ mozillaOrgFullDomainHash = domainFullHash;
+ mozillaOrgStrippedDomainHash = domainStrippedHash;
+ mozillaOrgBaseDomainHash = domainBaseHash;
+ } else {
+ // www.mozilla.org != mozilla.org
+ assertTrue("different full-domain hash for URL with prefix expected",
+ mozillaOrgFullDomainHash != domainFullHash);
+
+ // If the first URL contained foobar.mozilla.org, all later stripped-domains
+ // will be mozilla.org, i.e. will have a different hash.
+ // Otherwise only foobar.mozilla.org is different, and the other URL will
+ // have the same stripped domain.
+ // (In practice, foobar.mozilla.org is the last domain since it was addded last,
+ // but ordering isn't guaranteed hence we want to be able to handle any order.)
+ if (firstMozillaOrgURL.contains("foobar.mozilla.org") ||
+ (!firstMozillaOrgURL.contains("foobar.mozilla.org") &&
+ url.contains("foobar.mozilla.org"))) {
+ // foobar.mozilla.org != mozilla.org
+ assertTrue("different stripped-domain hash expected for URL with different stripped domain",
+ mozillaOrgStrippedDomainHash != domainStrippedHash);
+ } else {
+ // mozilla.org == mozilla.org
+ assertEquals("different stripped-domain hash for URL with same stripped domain",
+ mozillaOrgStrippedDomainHash, domainStrippedHash);
+ }
+
+ // mozilla.org == mozilla.org again
+ assertEquals("different base-domain hash for URL with same base domain",
+ mozillaOrgBaseDomainHash, domainBaseHash);
+ }
+ } else {
+ mozillaDeFullDomainHash = domainFullHash;
+ mozillaDeStrippedDomainHash = domainStrippedHash;
+ mozillaDeBaseDomainHash = domainBaseHash;
+ }
+ }
+
+ // Sanity checks to ensure we actually retrieved data in the loop above
+ assertTrue("Didn't find domain hashes for mozilla.org",
+ mozillaOrgFullDomainHash != -1);
+ assertTrue("Didn't find domain hashes for mozilla.de",
+ mozillaDeFullDomainHash != -1);
+
+ assertTrue("Different domain hashes expected for different domains",
+ mozillaDeFullDomainHash != mozillaOrgFullDomainHash);
+ assertTrue("Different domain hashes expected for different domains",
+ mozillaDeStrippedDomainHash != mozillaOrgStrippedDomainHash);
+ assertTrue("Different domain hashes expected for different domains",
+ mozillaDeBaseDomainHash != mozillaOrgBaseDomainHash);
+ } finally {
+ cursor.close();
+ }
+ }
+
+ @Test
+ public void testDomainHashCreationForBookmarks() throws Exception {
+ insertBookmarkItem("http://www.mozilla.org/");
+ insertBookmarkItem("http://mozilla.org/about/");
+ insertBookmarkItem("http://foobar.mozilla.org");
+ insertBookmarkItem("http://www.mozilla.de/");
+
+ final Cursor bookmarksCursor = bookmarksClient.query(bookmarksTestUri,
+ new String[]{
+ Bookmarks.URL,
+ Bookmarks.DOMAIN_FULL_HASH,
+ Bookmarks.DOMAIN_STRIPPED_HASH,
+ Bookmarks.DOMAIN_BASE_HASH
+ },
+ Bookmarks.TYPE + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
+ Bookmarks.IS_DELETED + " = 0",
+ null,
+ null
+ );
+
+ testFourItemCursor(bookmarksCursor,
+ Bookmarks.URL,
+ Bookmarks.DOMAIN_FULL_HASH,
+ Bookmarks.DOMAIN_STRIPPED_HASH,
+ Bookmarks.DOMAIN_BASE_HASH);
+ }
+
+ @Test
+ public void testDomainHashCreationForHistory() throws Exception {
+ insertHistoryItem("http://www.mozilla.org/", UUID.randomUUID().toString());
+ insertHistoryItem("http://mozilla.org/about/", UUID.randomUUID().toString());
+ insertHistoryItem("http://foobar.mozilla.org", UUID.randomUUID().toString());
+ insertHistoryItem("http://www.mozilla.de/", UUID.randomUUID().toString());
+
+ final Cursor historyCursor = historyClient.query(historyTestUri,
+ new String[]{
+ History.URL,
+ History.DOMAIN_FULL_HASH,
+ History.DOMAIN_STRIPPED_HASH,
+ History.DOMAIN_BASE_HASH
+ },
+ History.IS_DELETED + " = 0",
+ null,
+ null
+ );
+
+ testFourItemCursor(historyCursor,
+ History.URL,
+ History.DOMAIN_FULL_HASH,
+ History.DOMAIN_STRIPPED_HASH,
+ History.DOMAIN_BASE_HASH);
+ }
+
+ private void insertBookmarkItem(String url) throws RemoteException {
+ ContentValues values = new ContentValues();
+
+ values.put(BrowserContract.Bookmarks.URL, url);
+ // The title doesn't really matter in this test - let's just use a random string
+ values.put(BrowserContract.Bookmarks.TITLE, UUID.randomUUID().toString());
+ values.put(BrowserContract.Bookmarks.PARENT, 0);
+ values.put(BrowserContract.Bookmarks.TYPE, BrowserContract.Bookmarks.TYPE_BOOKMARK);
+ values.put(BrowserContract.Bookmarks.DATE_CREATED, System.currentTimeMillis());
+
+ bookmarksClient.insert(bookmarksTestUri, values);
+ }
+}