From 486c638063ebbea0179a13d65e6690b8bbaba840 Mon Sep 17 00:00:00 2001
From: Kihong Seong <kihongs@google.com>
Date: Mon, 12 Dec 2022 02:16:18 +0000
Subject: [PATCH] Add tests for BluetoothMapContentObserverTest

Bug: 237467631
Test: atest BluetoothMapContentObserverTest
Change-Id: I89f16b5064a65a86eb2ed547a55574b62290c1f5
Merged-In: I89f16b5064a65a86eb2ed547a55574b62290c1f5
(cherry picked from commit 96a49f6330f64c5fdb88b34d8a333e0cf957ba04)
---
 .../map/BluetoothMapContentObserver.java      |  67 +++--
 .../map/BluetoothMapContentObserverTest.java  | 232 ++++++++++++++----
 2 files changed, 220 insertions(+), 79 deletions(-)

diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
index 31ba0b11bb9..04d80a97b57 100644
--- a/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
+++ b/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
@@ -88,18 +88,30 @@ public class BluetoothMapContentObserver {
     private static final boolean D = BluetoothMapService.DEBUG;
     private static final boolean V = BluetoothMapService.VERBOSE;
 
-    private static final String EVENT_TYPE_NEW = "NewMessage";
-    private static final String EVENT_TYPE_DELETE = "MessageDeleted";
-    private static final String EVENT_TYPE_REMOVED = "MessageRemoved";
-    private static final String EVENT_TYPE_SHIFT = "MessageShift";
-    private static final String EVENT_TYPE_DELEVERY_SUCCESS = "DeliverySuccess";
-    private static final String EVENT_TYPE_SENDING_SUCCESS = "SendingSuccess";
-    private static final String EVENT_TYPE_SENDING_FAILURE = "SendingFailure";
-    private static final String EVENT_TYPE_DELIVERY_FAILURE = "DeliveryFailure";
-    private static final String EVENT_TYPE_READ_STATUS = "ReadStatusChanged";
-    private static final String EVENT_TYPE_CONVERSATION = "ConversationChanged";
-    private static final String EVENT_TYPE_PRESENCE = "ParticipantPresenceChanged";
-    private static final String EVENT_TYPE_CHAT_STATE = "ParticipantChatStateChanged";
+    @VisibleForTesting
+    static final String EVENT_TYPE_NEW = "NewMessage";
+    @VisibleForTesting
+    static final String EVENT_TYPE_DELETE = "MessageDeleted";
+    @VisibleForTesting
+    static final String EVENT_TYPE_REMOVED = "MessageRemoved";
+    @VisibleForTesting
+    static final String EVENT_TYPE_SHIFT = "MessageShift";
+    @VisibleForTesting
+    static final String EVENT_TYPE_DELEVERY_SUCCESS = "DeliverySuccess";
+    @VisibleForTesting
+    static final String EVENT_TYPE_SENDING_SUCCESS = "SendingSuccess";
+    @VisibleForTesting
+    static final String EVENT_TYPE_SENDING_FAILURE = "SendingFailure";
+    @VisibleForTesting
+    static final String EVENT_TYPE_DELIVERY_FAILURE = "DeliveryFailure";
+    @VisibleForTesting
+    static final String EVENT_TYPE_READ_STATUS = "ReadStatusChanged";
+    @VisibleForTesting
+    static final String EVENT_TYPE_CONVERSATION = "ConversationChanged";
+    @VisibleForTesting
+    static final String EVENT_TYPE_PRESENCE = "ParticipantPresenceChanged";
+    @VisibleForTesting
+    static final String EVENT_TYPE_CHAT_STATE = "ParticipantChatStateChanged";
 
     private static final long EVENT_FILTER_NEW_MESSAGE = 1L;
     private static final long EVENT_FILTER_MESSAGE_DELETED = 1L << 1;
@@ -337,11 +349,13 @@ public class BluetoothMapContentObserver {
         }
     }
 
-    private Map<Long, Msg> getMsgListSms() {
+    @VisibleForTesting
+    Map<Long, Msg> getMsgListSms() {
         return mMsgListSms;
     }
 
-    private void setMsgListSms(Map<Long, Msg> msgListSms, boolean changesDetected) {
+    @VisibleForTesting
+    void setMsgListSms(Map<Long, Msg> msgListSms, boolean changesDetected) {
         mMsgListSms = msgListSms;
         if (changesDetected) {
             mMasInstance.updateFolderVersionCounter();
@@ -349,13 +363,13 @@ public class BluetoothMapContentObserver {
         mMasInstance.setMsgListSms(msgListSms);
     }
 
-
-    private Map<Long, Msg> getMsgListMms() {
+    @VisibleForTesting
+    Map<Long, Msg> getMsgListMms() {
         return mMsgListMms;
     }
 
-
-    private void setMsgListMms(Map<Long, Msg> msgListMms, boolean changesDetected) {
+    @VisibleForTesting
+    void setMsgListMms(Map<Long, Msg> msgListMms, boolean changesDetected) {
         mMsgListMms = msgListMms;
         if (changesDetected) {
             mMasInstance.updateFolderVersionCounter();
@@ -363,13 +377,13 @@ public class BluetoothMapContentObserver {
         mMasInstance.setMsgListMms(msgListMms);
     }
 
-
-    private Map<Long, Msg> getMsgListMsg() {
+    @VisibleForTesting
+    Map<Long, Msg> getMsgListMsg() {
         return mMsgListMsg;
     }
 
-
-    private void setMsgListMsg(Map<Long, Msg> msgListMsg, boolean changesDetected) {
+    @VisibleForTesting
+    void setMsgListMsg(Map<Long, Msg> msgListMsg, boolean changesDetected) {
         mMsgListMsg = msgListMsg;
         if (changesDetected) {
             mMasInstance.updateFolderVersionCounter();
@@ -377,7 +391,8 @@ public class BluetoothMapContentObserver {
         mMasInstance.setMsgListMsg(msgListMsg);
     }
 
-    private Map<String, BluetoothMapConvoContactElement> getContactList() {
+    @VisibleForTesting
+    Map<String, BluetoothMapConvoContactElement> getContactList() {
         return mContactList;
     }
 
@@ -387,7 +402,8 @@ public class BluetoothMapContentObserver {
      * @param contactList
      * @param changesDetected that is not chat state changed nor presence state changed.
      */
-    private void setContactList(Map<String, BluetoothMapConvoContactElement> contactList,
+    @VisibleForTesting
+    void setContactList(Map<String, BluetoothMapConvoContactElement> contactList,
             boolean changesDetected) {
         mContactList = contactList;
         if (changesDetected) {
@@ -1117,7 +1133,8 @@ public class BluetoothMapContentObserver {
         }
     }
 
-    private void sendEvent(Event evt) {
+    @VisibleForTesting
+    void sendEvent(Event evt) {
 
         if (!mTransmitEvents) {
             if (V) {
diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java
index 71963c3b221..055ec2ea1a7 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java
@@ -23,6 +23,7 @@ import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserManager;
@@ -32,28 +33,47 @@ import android.telephony.TelephonyManager;
 import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.bluetooth.R;
+import com.android.obex.ResponseCodes;
 
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.IOException;
 import java.util.HashSet;
+import java.util.Map;
 
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class BluetoothMapContentObserverTest {
     static final String TEST_NUMBER_ONE = "5551212";
     static final String TEST_NUMBER_TWO = "5551234";
-    private Context mTargetContext;
+    static final int TEST_MAS_ID = 1;
+    static final long TEST_HANDLE = 1;
+
+    @Mock
+    private BluetoothMnsObexClient mClient;
+    @Mock
+    private BluetoothMapMasInstance mInstance;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private UserManager mUserService;
+    @Mock
+    private Context mContext;
+
+    private ExceptionTestProvider mProvider;
+    private MockContentResolver mMockContentResolver;
+    private BluetoothMapContentObserver mObserver;
 
     static class ExceptionTestProvider extends MockContentProvider {
         HashSet<String> mContents = new HashSet<String>();
@@ -83,44 +103,28 @@ public class BluetoothMapContentObserverTest {
     }
 
     @Before
-    public void setUp() {
-        mTargetContext = InstrumentationRegistry.getTargetContext();
+    public void setUp() throws Exception {
         Assume.assumeTrue("Ignore test when BluetoothMapService is not enabled",
                 BluetoothMapService.isEnabled());
-    }
-
-    @Test
-    public void testInitMsgList() {
+        MockitoAnnotations.initMocks(this);
         if (Looper.myLooper() == null) {
             Looper.prepare();
         }
-        Context mockContext = mock(Context.class);
-        MockContentResolver mockResolver = new MockContentResolver();
-        ExceptionTestProvider mockProvider = new ExceptionTestProvider(mockContext);
-        mockResolver.addProvider("sms", mockProvider);
-
-        TelephonyManager mockTelephony = mock(TelephonyManager.class);
-        UserManager mockUserService = mock(UserManager.class);
-        BluetoothMapMasInstance mockMas = mock(BluetoothMapMasInstance.class);
+        mMockContentResolver = new MockContentResolver();
+        mProvider = new ExceptionTestProvider(mContext);
+        mMockContentResolver.addProvider("sms", mProvider);
 
         // Functions that get called when BluetoothMapContentObserver is created
-        when(mockUserService.isUserUnlocked()).thenReturn(true);
-        when(mockContext.getContentResolver()).thenReturn(mockResolver);
-        when(mockContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mockTelephony);
-        when(mockContext.getSystemServiceName(TelephonyManager.class))
+        when(mUserService.isUserUnlocked()).thenReturn(true);
+        when(mContext.getContentResolver()).thenReturn(mMockContentResolver);
+        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+        when(mContext.getSystemServiceName(TelephonyManager.class))
                 .thenReturn(Context.TELEPHONY_SERVICE);
-        when(mockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mockUserService);
-        when(mockContext.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserService);
+        when(mContext.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE);
+        when(mInstance.getMasId()).thenReturn(TEST_MAS_ID);
 
-        BluetoothMapContentObserver observer;
-        try {
-            // The constructor of BluetoothMapContentObserver calls initMsgList
-            observer = new BluetoothMapContentObserver(mockContext, null, mockMas, null, true);
-        } catch (RemoteException e) {
-            Assert.fail("Failed to created BluetoothMapContentObserver object");
-        } catch (SQLiteException e) {
-            Assert.fail("Threw SQLiteException instead of Assert.failing cleanly");
-        }
+        mObserver = new BluetoothMapContentObserver(mContext, mClient, mInstance, null, true);
     }
 
     @Test
@@ -128,25 +132,8 @@ public class BluetoothMapContentObserverTest {
         if (Looper.myLooper() == null) {
             Looper.prepare();
         }
-        Context mockContext = mock(Context.class);
-        MockContentResolver mockResolver = new MockContentResolver();
-        ExceptionTestProvider mockProvider = new ExceptionTestProvider(mockContext);
-
-        mockResolver.addProvider("sms", mockProvider);
-        mockResolver.addProvider("mms", mockProvider);
-        mockResolver.addProvider("mms-sms", mockProvider);
-        TelephonyManager mockTelephony = mock(TelephonyManager.class);
-        UserManager mockUserService = mock(UserManager.class);
-        BluetoothMapMasInstance mockMas = mock(BluetoothMapMasInstance.class);
-
-        // Functions that get called when BluetoothMapContentObserver is created
-        when(mockUserService.isUserUnlocked()).thenReturn(true);
-        when(mockContext.getContentResolver()).thenReturn(mockResolver);
-        when(mockContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mockTelephony);
-        when(mockContext.getSystemServiceName(TelephonyManager.class))
-                .thenReturn(Context.TELEPHONY_SERVICE);
-        when(mockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mockUserService);
-        when(mockContext.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE);
+        mMockContentResolver.addProvider("mms", mProvider);
+        mMockContentResolver.addProvider("mms-sms", mProvider);
 
         BluetoothMapbMessageMime message = new BluetoothMapbMessageMime();
         message.setType(BluetoothMapUtils.TYPE.MMS);
@@ -168,7 +155,7 @@ public class BluetoothMapContentObserverTest {
         try {
             // The constructor of BluetoothMapContentObserver calls initMsgList
             BluetoothMapContentObserver observer =
-                    new BluetoothMapContentObserver(mockContext, null, mockMas, null, true);
+                    new BluetoothMapContentObserver(mContext, null, mInstance, null, true);
             observer.pushMessage(message, folderElement, appParams, null);
         } catch (RemoteException e) {
             Assert.fail("Failed to created BluetoothMapContentObserver object");
@@ -182,9 +169,146 @@ public class BluetoothMapContentObserverTest {
         }
 
         // Validate that 3 addresses were inserted into the database with 2 being the recipients
-        Assert.assertEquals(3, mockProvider.mContents.size());
-        Assert.assertTrue(mockProvider.mContents.contains(TEST_NUMBER_ONE));
-        Assert.assertTrue(mockProvider.mContents.contains(TEST_NUMBER_TWO));
+        Assert.assertEquals(3, mProvider.mContents.size());
+        Assert.assertTrue(mProvider.mContents.contains(TEST_NUMBER_ONE));
+        Assert.assertTrue(mProvider.mContents.contains(TEST_NUMBER_TWO));
+    }
+
+    @Test
+    public void testSendEvent_withZeroEventFilter() {
+        when(mClient.isConnected()).thenReturn(true);
+        mObserver.setNotificationFilter(0);
+
+        String eventType = BluetoothMapContentObserver.EVENT_TYPE_NEW;
+        BluetoothMapContentObserver.Event event = mObserver.new Event(eventType, TEST_HANDLE, null,
+                null);
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_DELETE;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_REMOVED;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_SHIFT;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_DELEVERY_SUCCESS;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_SENDING_SUCCESS;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_SENDING_FAILURE;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_READ_STATUS;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_CONVERSATION;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_PRESENCE;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+
+        event.eventType = BluetoothMapContentObserver.EVENT_TYPE_CHAT_STATE;
+        mObserver.sendEvent(event);
+        verify(mClient, never()).sendEvent(any(), anyInt());
+    }
+
+    @Test
+    public void testEvent_withNonZeroEventFilter() throws Exception {
+        when(mClient.isConnected()).thenReturn(true);
+
+        String eventType = BluetoothMapContentObserver.EVENT_TYPE_NEW;
+        BluetoothMapContentObserver.Event event = mObserver.new Event(eventType, TEST_HANDLE, null,
+                null);
+
+        mObserver.sendEvent(event);
+
+        verify(mClient).sendEvent(event.encode(), TEST_MAS_ID);
     }
 
+    @Test
+    public void testSetContactList() {
+        Map<String, BluetoothMapConvoContactElement> map = Map.of();
+
+        mObserver.setContactList(map, true);
+
+        Assert.assertEquals(mObserver.getContactList(), map);
+    }
+
+    @Test
+    public void testSetMsgListSms() {
+        Map<Long, BluetoothMapContentObserver.Msg> map = Map.of();
+
+        mObserver.setMsgListSms(map, true);
+
+        Assert.assertEquals(mObserver.getMsgListSms(), map);
+    }
+
+    @Test
+    public void testSetMsgListMsg() {
+        Map<Long, BluetoothMapContentObserver.Msg> map = Map.of();
+
+        mObserver.setMsgListMsg(map, true);
+
+        Assert.assertEquals(mObserver.getMsgListMsg(), map);
+    }
+
+    @Test
+    public void testSetMsgListMms() {
+        Map<Long, BluetoothMapContentObserver.Msg> map = Map.of();
+
+        mObserver.setMsgListMms(map, true);
+
+        Assert.assertEquals(mObserver.getMsgListMms(), map);
+    }
+
+    @Test
+    public void testSetNotificationRegistration_withNullHandler() throws Exception {
+        when(mClient.getMessageHandler()).thenReturn(null);
+
+        Assert.assertEquals(
+                mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO),
+                ResponseCodes.OBEX_HTTP_UNAVAILABLE);
+    }
+
+    @Test
+    public void testSetNotificationRegistration_withInvalidMnsRecord() throws Exception {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        Handler handler = new Handler();
+        when(mClient.getMessageHandler()).thenReturn(handler);
+        when(mClient.isValidMnsRecord()).thenReturn(false);
+
+        Assert.assertEquals(
+                mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO),
+                ResponseCodes.OBEX_HTTP_OK);
+    }
+
+    @Test
+    public void testSetNotificationRegistration_withValidMnsRecord() throws Exception {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        Handler handler = new Handler();
+        when(mClient.getMessageHandler()).thenReturn(handler);
+        when(mClient.isValidMnsRecord()).thenReturn(true);
+
+        Assert.assertEquals(
+                mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO),
+                ResponseCodes.OBEX_HTTP_OK);
+    }
 }
-- 
GitLab