Merge "Add unit tests to com.android.server.nearby.fastpair.cache" into tm-mainline-prod
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/cache/DiscoveryItem.java b/nearby/service/java/com/android/server/nearby/fastpair/cache/DiscoveryItem.java
index 6065f99..961fe7a 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/cache/DiscoveryItem.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/cache/DiscoveryItem.java
@@ -28,6 +28,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.nearby.common.ble.util.RangingUtils;
 import com.android.server.nearby.common.fastpair.IconUtils;
 import com.android.server.nearby.common.locator.Locator;
@@ -295,7 +296,8 @@
      * Returns the app name of discovery item.
      */
     @Nullable
-    private String getAppName() {
+    @VisibleForTesting
+    protected String getAppName() {
         return mStoredDiscoveryItem.getAppName();
     }
 
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/cache/DiscoveryItemTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/cache/DiscoveryItemTest.java
new file mode 100644
index 0000000..1aaed5d
--- /dev/null
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/cache/DiscoveryItemTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2022 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.server.nearby.fastpair.cache;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.nearby.common.locator.LocatorContextWrapper;
+import com.android.server.nearby.fastpair.FastPairManager;
+import com.android.server.nearby.fastpair.testing.FakeDiscoveryItems;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unit tests for {@link DiscoveryItem} */
+public class DiscoveryItemTest {
+    private static final String DEFAULT_MAC_ADDRESS = "00:11:22:33:44:55";
+    private static final String DEFAULT_DESCRIPITON = "description";
+    private static final long DEFAULT_TIMESTAMP = 1000000000L;
+    private static final String DEFAULT_TITLE = "title";
+    private static final String APP_NAME = "app_name";
+    private static final String ACTION_URL =
+            "intent:#Intent;action=com.android.server.nearby:ACTION_FAST_PAIR;"
+            + "package=com.google.android.gms;"
+            + "component=com.google.android.gms/"
+            + ".nearby.discovery.service.DiscoveryService;end";
+    private static final String TRIGGER_ID = "trigger.id";
+    private static final String FAST_PAIR_ID = "id";
+    private static final int RSSI = -80;
+    private static final int TX_POWER = -10;
+
+    @Mock private Context mContext;
+    private LocatorContextWrapper mLocatorContextWrapper;
+    private FastPairCacheManager mFastPairCacheManager;
+    private FastPairManager mFastPairManager;
+    private DiscoveryItem mDiscoveryItem;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mLocatorContextWrapper = new LocatorContextWrapper(mContext);
+        mFastPairManager = new FastPairManager(mLocatorContextWrapper);
+        mFastPairCacheManager = mLocatorContextWrapper.getLocator().get(FastPairCacheManager.class);
+        when(mContext.getContentResolver()).thenReturn(
+                InstrumentationRegistry.getInstrumentation().getContext().getContentResolver());
+        mDiscoveryItem =
+                FakeDiscoveryItems.newFastPairDiscoveryItem(mLocatorContextWrapper);
+    }
+
+    @Test
+    public void testMultipleFields() {
+        assertThat(mDiscoveryItem.getId()).isEqualTo(FAST_PAIR_ID);
+        assertThat(mDiscoveryItem.getDescription()).isEqualTo(DEFAULT_DESCRIPITON);
+        assertThat(mDiscoveryItem.getTriggerId()).isEqualTo(TRIGGER_ID);
+        assertThat(mDiscoveryItem.getMacAddress()).isEqualTo(DEFAULT_MAC_ADDRESS);
+        assertThat(
+                mDiscoveryItem.getFirstObservationTimestampMillis()).isEqualTo(DEFAULT_TIMESTAMP);
+        assertThat(
+                mDiscoveryItem.getLastObservationTimestampMillis()).isEqualTo(DEFAULT_TIMESTAMP);
+        assertThat(mDiscoveryItem.getActionUrl()).isEqualTo(ACTION_URL);
+        assertThat(mDiscoveryItem.getAppName()).isEqualTo(APP_NAME);
+        assertThat(mDiscoveryItem.getRssi()).isEqualTo(RSSI);
+        assertThat(mDiscoveryItem.getTxPower()).isEqualTo(TX_POWER);
+    }
+
+    @Test
+    public void isMute() {
+        assertThat(mDiscoveryItem.isMuted()).isFalse();
+    }
+
+    @Test
+    public void itemWithDefaultDescription_shouldShowUp() {
+        assertThat(mDiscoveryItem.isReadyForDisplay()).isFalse();
+
+        // Null description should not show up.
+        mDiscoveryItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID,  null,
+                        TRIGGER_ID,  DEFAULT_MAC_ADDRESS,  "", RSSI, TX_POWER));
+        assertThat(mDiscoveryItem.isReadyForDisplay()).isFalse();
+
+        // Empty description should not show up.
+        mDiscoveryItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID,  "",
+                        TRIGGER_ID,  DEFAULT_MAC_ADDRESS, DEFAULT_TITLE, RSSI, TX_POWER));
+        assertThat(mDiscoveryItem.isReadyForDisplay()).isFalse();
+    }
+
+    @Test
+    public void itemWithEmptyTitle_shouldNotShowUp() {
+        // Null title should not show up.
+        assertThat(mDiscoveryItem.isReadyForDisplay()).isFalse();
+        // Empty title should not show up.
+        mDiscoveryItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, DEFAULT_MAC_ADDRESS, "", RSSI, TX_POWER));
+        assertThat(mDiscoveryItem.isReadyForDisplay()).isFalse();
+
+        // Null title should not show up.
+        mDiscoveryItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, DEFAULT_MAC_ADDRESS, null, RSSI, TX_POWER));
+        assertThat(mDiscoveryItem.isReadyForDisplay()).isFalse();
+    }
+
+    @Test
+    public void itemWithRssiAndTxPower_shouldHaveCorrectEstimatedDistance() {
+        assertThat(mDiscoveryItem.getEstimatedDistance()).isWithin(0.01).of(28.18);
+    }
+
+    @Test
+    public void itemWithoutRssiOrTxPower_shouldNotHaveEstimatedDistance() {
+        mDiscoveryItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, DEFAULT_MAC_ADDRESS, "", 0, 0));
+        assertThat(mDiscoveryItem.getEstimatedDistance()).isWithin(0.01).of(0);
+    }
+
+    @Test
+    public void getUiHashCode_differentAddress_differentHash() {
+        mDiscoveryItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, "00:11:22:33:44:55", "", RSSI, TX_POWER));
+        DiscoveryItem compareTo =
+                FakeDiscoveryItems.newFastPairDiscoveryItem(mLocatorContextWrapper);
+        compareTo.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, "55:44:33:22:11:00", "", RSSI, TX_POWER));
+        assertThat(mDiscoveryItem.getUiHashCode()).isNotEqualTo(compareTo.getUiHashCode());
+    }
+
+    @Test
+    public void getUiHashCode_sameAddress_sameHash() {
+        mDiscoveryItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, "00:11:22:33:44:55", "", RSSI, TX_POWER));
+        DiscoveryItem compareTo =
+                FakeDiscoveryItems.newFastPairDiscoveryItem(mLocatorContextWrapper);
+        compareTo.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, "00:11:22:33:44:55", "", RSSI, TX_POWER));
+        assertThat(mDiscoveryItem.getUiHashCode()).isEqualTo(compareTo.getUiHashCode());
+    }
+
+    @Test
+    public void isFastPair() {
+        DiscoveryItem fastPairItem =
+                FakeDiscoveryItems.newFastPairDiscoveryItem(mLocatorContextWrapper);
+        assertThat(fastPairItem.isFastPair()).isTrue();
+    }
+
+    @Test
+    public void testEqual() {
+        DiscoveryItem fastPairItem =
+                FakeDiscoveryItems.newFastPairDiscoveryItem(mLocatorContextWrapper);
+        assertThat(mDiscoveryItem.equals(fastPairItem)).isTrue();
+    }
+
+    @Test
+    public void testCopyOfStoredItem() {
+        DiscoveryItem fastPairItem =
+                FakeDiscoveryItems.newFastPairDiscoveryItem(mLocatorContextWrapper);
+        fastPairItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, "00:11:22:33:44:55", "", RSSI, TX_POWER));
+        assertThat(mDiscoveryItem.equals(fastPairItem)).isFalse();
+        fastPairItem.setStoredItemForTest(mDiscoveryItem.getCopyOfStoredItem());
+        assertThat(mDiscoveryItem.equals(fastPairItem)).isTrue();
+    }
+
+    @Test
+    public void testStoredItemForTest() {
+        DiscoveryItem fastPairItem =
+                FakeDiscoveryItems.newFastPairDiscoveryItem(mLocatorContextWrapper);
+        fastPairItem.setStoredItemForTest(
+                FakeDiscoveryItems.newFastPairDeviceStoredItem(FAST_PAIR_ID, DEFAULT_DESCRIPITON,
+                        TRIGGER_ID, "00:11:22:33:44:55", "", RSSI, TX_POWER));
+        assertThat(mDiscoveryItem.equals(fastPairItem)).isFalse();
+        fastPairItem.setStoredItemForTest(mDiscoveryItem.getStoredItemForTest());
+        assertThat(mDiscoveryItem.equals(fastPairItem)).isTrue();
+    }
+}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/testing/FakeDiscoveryItems.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/testing/FakeDiscoveryItems.java
index c406e47..e289543 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/testing/FakeDiscoveryItems.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/testing/FakeDiscoveryItems.java
@@ -22,10 +22,16 @@
 import service.proto.Cache;
 
 public class FakeDiscoveryItems {
-    public static final String DEFAULT_MAC_ADDRESS = "00:11:22:33:44:55";
-    public static final long DEFAULT_TIMESTAMP = 1000000000L;
-    public static final String DEFAULT_DESCRIPITON = "description";
-    public static final String TRIGGER_ID = "trigger.id";
+    private static final String DEFAULT_MAC_ADDRESS = "00:11:22:33:44:55";
+    private static final long DEFAULT_TIMESTAMP = 1000000000L;
+    private static final String DEFAULT_DESCRIPITON = "description";
+    private static final String APP_NAME = "app_name";
+    private static final String ACTION_URL =
+            "intent:#Intent;action=com.android.server.nearby:ACTION_FAST_PAIR;"
+                    + "package=com.google.android.gms;"
+                    + "component=com.google.android.gms/"
+                    + ".nearby.discovery.service.DiscoveryService;end";
+    private static final String TRIGGER_ID = "trigger.id";
     private static final String FAST_PAIR_ID = "id";
     private static final int RSSI = -80;
     private static final int TX_POWER = -10;
@@ -46,9 +52,35 @@
         item.setMacAddress(DEFAULT_MAC_ADDRESS);
         item.setFirstObservationTimestampMillis(DEFAULT_TIMESTAMP);
         item.setLastObservationTimestampMillis(DEFAULT_TIMESTAMP);
+        item.setActionUrl(ACTION_URL);
+        item.setAppName(APP_NAME);
         item.setRssi(RSSI);
         item.setTxPower(TX_POWER);
         return item.build();
     }
 
+    public static Cache.StoredDiscoveryItem newFastPairDeviceStoredItem(String id,
+            String description, String triggerId, String macAddress, String title,
+            int rssi, int txPower) {
+        Cache.StoredDiscoveryItem.Builder item = Cache.StoredDiscoveryItem.newBuilder();
+        item.setState(Cache.StoredDiscoveryItem.State.STATE_ENABLED);
+        if (id != null) {
+            item.setId(id);
+        }
+        if (description != null) {
+            item.setDescription(description);
+        }
+        if (triggerId != null) {
+            item.setTriggerId(triggerId);
+        }
+        if (macAddress != null) {
+            item.setMacAddress(macAddress);
+        }
+        if (title != null) {
+            item.setTitle(title);
+        }
+        item.setRssi(rssi);
+        item.setTxPower(txPower);
+        return item.build();
+    }
 }