1 /*
2  * Copyright 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.map;
18 
19 import static org.mockito.Mockito.*;
20 
21 import android.content.ContentValues;
22 import android.content.Context;
23 import android.database.Cursor;
24 import android.database.sqlite.SQLiteException;
25 import android.net.Uri;
26 import android.os.Looper;
27 import android.os.RemoteException;
28 import android.os.UserManager;
29 import android.provider.Telephony.Mms;
30 import android.provider.Telephony.Sms;
31 import android.telephony.TelephonyManager;
32 import android.test.mock.MockContentProvider;
33 import android.test.mock.MockContentResolver;
34 
35 import androidx.test.InstrumentationRegistry;
36 import androidx.test.filters.MediumTest;
37 import androidx.test.runner.AndroidJUnit4;
38 
39 import com.android.bluetooth.R;
40 
41 import org.junit.Assert;
42 import org.junit.Assume;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.junit.runner.RunWith;
46 import org.mockito.Mockito;
47 
48 import java.io.IOException;
49 import java.util.HashSet;
50 
51 @MediumTest
52 @RunWith(AndroidJUnit4.class)
53 public class BluetoothMapContentObserverTest {
54     static final String TEST_NUMBER_ONE = "5551212";
55     static final String TEST_NUMBER_TWO = "5551234";
56     private Context mTargetContext;
57 
58     static class ExceptionTestProvider extends MockContentProvider {
59         HashSet<String> mContents = new HashSet<String>();
ExceptionTestProvider(Context context)60         public ExceptionTestProvider(Context context) {
61             super(context);
62         }
63 
64         @Override
query(Uri uri, String[] b, String s, String[] c, String d)65         public Cursor query(Uri uri, String[] b, String s, String[] c, String d) {
66             // Throw exception for SMS queries for easy initialization
67             if (Sms.CONTENT_URI.equals(uri)) throw new SQLiteException();
68 
69             // Return a cursor otherwise for Thread IDs
70             Cursor cursor = Mockito.mock(Cursor.class);
71             when(cursor.moveToFirst()).thenReturn(true);
72             when(cursor.getLong(anyInt())).thenReturn(0L);
73             return cursor;
74         }
75 
76         @Override
insert(Uri uri, ContentValues values)77         public Uri insert(Uri uri, ContentValues values) {
78             // Store addresses for later verification
79             Object address = values.get(Mms.Addr.ADDRESS);
80             if (address != null) mContents.add((String) address);
81             return Uri.withAppendedPath(Mms.Outbox.CONTENT_URI, "0");
82         }
83     }
84 
85     @Before
setUp()86     public void setUp() {
87         mTargetContext = InstrumentationRegistry.getTargetContext();
88         Assume.assumeTrue("Ignore test when BluetoothMapService is not enabled",
89                 mTargetContext.getResources().getBoolean(R.bool.profile_supported_map));
90     }
91 
92     @Test
testInitMsgList()93     public void testInitMsgList() {
94         if (Looper.myLooper() == null) {
95             Looper.prepare();
96         }
97         Context mockContext = mock(Context.class);
98         MockContentResolver mockResolver = new MockContentResolver();
99         ExceptionTestProvider mockProvider = new ExceptionTestProvider(mockContext);
100         mockResolver.addProvider("sms", mockProvider);
101 
102         TelephonyManager mockTelephony = mock(TelephonyManager.class);
103         UserManager mockUserService = mock(UserManager.class);
104         BluetoothMapMasInstance mockMas = mock(BluetoothMapMasInstance.class);
105 
106         // Functions that get called when BluetoothMapContentObserver is created
107         when(mockUserService.isUserUnlocked()).thenReturn(true);
108         when(mockContext.getContentResolver()).thenReturn(mockResolver);
109         when(mockContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mockTelephony);
110         when(mockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mockUserService);
111 
112         BluetoothMapContentObserver observer;
113         try {
114             // The constructor of BluetoothMapContentObserver calls initMsgList
115             observer = new BluetoothMapContentObserver(mockContext, null, mockMas, null, true);
116         } catch (RemoteException e) {
117             Assert.fail("Failed to created BluetoothMapContentObserver object");
118         } catch (SQLiteException e) {
119             Assert.fail("Threw SQLiteException instead of Assert.failing cleanly");
120         }
121     }
122 
123     @Test
testPushGroupMMS()124     public void testPushGroupMMS() {
125         if (Looper.myLooper() == null) {
126             Looper.prepare();
127         }
128         Context mockContext = mock(Context.class);
129         MockContentResolver mockResolver = new MockContentResolver();
130         ExceptionTestProvider mockProvider = new ExceptionTestProvider(mockContext);
131 
132         mockResolver.addProvider("sms", mockProvider);
133         mockResolver.addProvider("mms", mockProvider);
134         mockResolver.addProvider("mms-sms", mockProvider);
135         TelephonyManager mockTelephony = mock(TelephonyManager.class);
136         UserManager mockUserService = mock(UserManager.class);
137         BluetoothMapMasInstance mockMas = mock(BluetoothMapMasInstance.class);
138 
139         // Functions that get called when BluetoothMapContentObserver is created
140         when(mockUserService.isUserUnlocked()).thenReturn(true);
141         when(mockContext.getContentResolver()).thenReturn(mockResolver);
142         when(mockContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mockTelephony);
143         when(mockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mockUserService);
144 
145         BluetoothMapbMessageMime message = new BluetoothMapbMessageMime();
146         message.setType(BluetoothMapUtils.TYPE.MMS);
147         message.setFolder("telecom/msg/outbox");
148         message.addSender("Zero", "0");
149         message.addRecipient("One", new String[] {TEST_NUMBER_ONE}, null);
150         message.addRecipient("Two", new String[] {TEST_NUMBER_TWO}, null);
151         BluetoothMapbMessageMime.MimePart body =  message.addMimePart();
152         try {
153             body.mContentType = "text/plain";
154             body.mData = "HelloWorld".getBytes("utf-8");
155         } catch (Exception e) {
156             Assert.fail("Failed to setup test message");
157         }
158 
159         BluetoothMapAppParams appParams = new BluetoothMapAppParams();
160         BluetoothMapFolderElement folderElement = new BluetoothMapFolderElement("outbox", null);
161 
162         try {
163             // The constructor of BluetoothMapContentObserver calls initMsgList
164             BluetoothMapContentObserver observer =
165                     new BluetoothMapContentObserver(mockContext, null, mockMas, null, true);
166             observer.pushMessage(message, folderElement, appParams, null);
167         } catch (RemoteException e) {
168             Assert.fail("Failed to created BluetoothMapContentObserver object");
169         } catch (SQLiteException e) {
170             Assert.fail("Threw SQLiteException instead of Assert.failing cleanly");
171         } catch (IOException e) {
172             Assert.fail("Threw IOException");
173         } catch (NullPointerException e) {
174             //expected that the test case will end in a NPE as part of the sendMultimediaMessage
175             //pendingSendIntent
176         }
177 
178         // Validate that 3 addresses were inserted into the database with 2 being the recipients
179         Assert.assertEquals(3, mockProvider.mContents.size());
180         Assert.assertTrue(mockProvider.mContents.contains(TEST_NUMBER_ONE));
181         Assert.assertTrue(mockProvider.mContents.contains(TEST_NUMBER_TWO));
182     }
183 
184 }
185