1c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu/*
2c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * Copyright (C) 2017 The Android Open Source Project
3c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *
4c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * Licensed under the Apache License, Version 2.0 (the "License");
5c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * you may not use this file except in compliance with the License.
6c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * You may obtain a copy of the License at
7c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *
8c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *      http://www.apache.org/licenses/LICENSE-2.0
9c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *
10c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * Unless required by applicable law or agreed to in writing, software
11c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * distributed under the License is distributed on an "AS IS" BASIS,
12c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * See the License for the specific language governing permissions and
14c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * limitations under the License
15c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu */
16c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
17c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxupackage com.android.providers.telephony;
18c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
19c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.app.AppOpsManager;
20c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.content.ContentValues;
21c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.content.Context;
22c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.content.pm.PackageManager;
23c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.content.pm.ProviderInfo;
24c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.content.res.Resources;
25c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.database.ContentObserver;
26c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.net.Uri;
27c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.provider.Telephony;
28c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.telephony.TelephonyManager;
29c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.test.mock.MockContentResolver;
30c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.test.mock.MockContext;
31c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.test.suitebuilder.annotation.SmallTest;
32c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport android.util.Log;
33c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
34c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport junit.framework.TestCase;
35c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
36c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport org.junit.Test;
37c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxuimport org.mockito.Mockito;
38c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
39c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
40c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu/**
41c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * Tests for testing CRUD operations of SmsProvider.
42c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * Uses a MockContentResolver to test insert
43c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * Uses SmsProviderTestable to set up in-memory database
44c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *
45c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu * Build, install and run the tests by running the commands below:
46c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *     runtest --path <dir or file>
47c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *     runtest --path <dir or file> --test-method <testMethodName>
48c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *     e.g.)
49c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *         runtest --path tests/src/com/android/providers/telephony/SmsProviderTest.java \
50c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu *                 --test-method testInsertUri
51c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu */
52c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxupublic class SmsProviderTest extends TestCase {
53c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    private static final String TAG = "TelephonyProviderTest";
54c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
55c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    private MockContextWithProvider mContext;
56c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    private MockContentResolver mContentResolver;
57c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    private SmsProviderTestable mSmsProviderTestable;
58c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
59c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    private int notifyChangeCount;
60c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
61c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
62c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    /**
63c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu     * This is used to give the SmsProviderTest a mocked context which takes a
64c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu     * SmsProvider and attaches it to the ContentResolver with telephony authority.
65c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu     * The mocked context also gives WRITE_APN_SETTINGS permissions
66c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu     */
67c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    private class MockContextWithProvider extends MockContext {
68c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        private final MockContentResolver mResolver;
69c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
70c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        public MockContextWithProvider(SmsProvider smsProvider) {
71c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            mResolver = new MockContentResolver() {
72c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                @Override
73c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
74c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                        int userHandle) {
75c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                    notifyChangeCount++;
76c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                }
77c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            };
78c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
79c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            // Add authority="sms" to given smsProvider
80c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            ProviderInfo providerInfo = new ProviderInfo();
81c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            providerInfo.authority = "sms";
82c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
83c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            // Add context to given smsProvider
84c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            smsProvider.attachInfoForTesting(this, providerInfo);
85c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            Log.d(TAG, "MockContextWithProvider: smsProvider.getContext(): "
86c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                    + smsProvider.getContext());
87c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
88c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            // Add given SmsProvider to mResolver with authority="sms" so that
89c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            // mResolver can send queries to mSmsProvider
90c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            mResolver.addProvider("sms", smsProvider);
91c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            Log.d(TAG, "MockContextWithProvider: Add SmsProvider to mResolver");
92c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        }
93c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
94c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        @Override
95c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        public Object getSystemService(String name) {
96c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            Log.d(TAG, "getSystemService: returning null");
97c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            switch (name) {
98c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                case Context.APP_OPS_SERVICE:
99c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                    return Mockito.mock(AppOpsManager.class);
100c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                case Context.TELEPHONY_SERVICE:
101c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                    return Mockito.mock(TelephonyManager.class);
102c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                default:
103c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                    return null;
104c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            }
105c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        }
106c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
107c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        @Override
108c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        public Resources getResources() {
109c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            Log.d(TAG, "getResources: returning null");
110c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            return null;
111c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        }
112c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
113c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        @Override
114c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        public int getUserId() {
115c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            return 0;
116c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        }
117c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
118c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        @Override
119c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        public MockContentResolver getContentResolver() {
120c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            return mResolver;
121c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        }
122c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
123c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        @Override
124c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        public int checkCallingOrSelfPermission(String permission) {
125c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu            return PackageManager.PERMISSION_GRANTED;
126c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        }
127c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    }
128c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
129c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    @Override
130c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    protected void setUp() throws Exception {
131c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        super.setUp();
132c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        mSmsProviderTestable = new SmsProviderTestable();
133c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        mContext = new MockContextWithProvider(mSmsProviderTestable);
134c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        mContentResolver = mContext.getContentResolver();
135c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        notifyChangeCount = 0;
136c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    }
137c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
138c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    @Override
139c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    protected void tearDown() throws Exception {
140c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        super.tearDown();
141c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        mSmsProviderTestable.closeDatabase();
142c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    }
143c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
144c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    @Test
145c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    @SmallTest
146c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    public void testInsertUri() {
147c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        // insert test contentValues
148c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        final ContentValues values = new ContentValues();
149c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put(Telephony.Sms.SUBSCRIPTION_ID, 1);
150c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put(Telephony.Sms.ADDRESS, "12345");
151c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put(Telephony.Sms.BODY, "test");
152c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put(Telephony.Sms.DATE, System.currentTimeMillis()); // milliseconds
153c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put(Telephony.Sms.SEEN, 1);
154c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put(Telephony.Sms.READ, 1);
155c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put(Telephony.Sms.THREAD_ID, 1);
156c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
157c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        // test for sms table
158c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        Log.d(TAG, "testInsertSmsTable Inserting contentValues: " + values);
159c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        assertEquals(Uri.parse("content://sms/1"),
160c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                mContentResolver.insert(Uri.parse("content://sms"), values));
161c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        assertEquals(Uri.parse("content://sms/2"),
162c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                mContentResolver.insert(Uri.parse("content://sms"), values));
163c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu
164c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        // test for attachments table
165c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.clear();
166c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put("sms_id", 1);
167c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put("content_url", "test");
168c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        values.put("offset", 0);
169c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        Log.d(TAG, "testInsertAttachmentTable Inserting contentValues: " + values);
170c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu        assertEquals(Uri.parse("content://sms/attachments/1"),
171c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu                mContentResolver.insert(Uri.parse("content://sms/attachments"), values));
172c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu    }
173c1f7e0a116f7d3a20992e50a8e803eca6803370ffionaxu}