1 /*
2  * Copyright (C) 2019 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 android.content.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.fail;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.eq;
24 import static org.mockito.Mockito.CALLS_REAL_METHODS;
25 import static org.mockito.Mockito.RETURNS_DEFAULTS;
26 import static org.mockito.Mockito.doReturn;
27 import static org.mockito.Mockito.mock;
28 
29 import android.content.ContentProvider;
30 import android.content.ContentProviderOperation;
31 import android.content.ContentProviderResult;
32 import android.content.ContentResolver;
33 import android.content.ContentValues;
34 import android.content.Context;
35 import android.content.pm.ProviderInfo;
36 import android.content.res.AssetFileDescriptor;
37 import android.database.Cursor;
38 import android.database.MatrixCursor;
39 import android.net.Uri;
40 import android.os.Bundle;
41 import android.os.CancellationSignal;
42 import android.os.ParcelFileDescriptor;
43 import android.util.Size;
44 
45 import androidx.test.runner.AndroidJUnit4;
46 
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 
51 import java.io.File;
52 import java.io.IOException;
53 import java.util.ArrayList;
54 
55 @RunWith(AndroidJUnit4.class)
56 public class ContentResolverWrapTest {
57     private static final String AUTHORITY = "com.example";
58     private static final Uri URI = Uri.parse("content://" + AUTHORITY);
59     private static final ArrayList<ContentProviderOperation> OPERATIONS = new ArrayList<>();
60     private static final ContentProviderResult[] RESULTS = new ContentProviderResult[0];
61     private static final ContentValues VALUES = new ContentValues();
62     private static final ContentValues[] VALUES_ARRAY = new ContentValues[0];
63     private static final String METHOD = "method";
64     private static final String ARG = "arg";
65     private static final String[] ARG_ARRAY = new String[0];
66     private static final Bundle EXTRAS = new Bundle();
67     private static final String TYPE = "mime/type";
68     private static final String[] TYPE_ARRAY = new String[0];
69     private static final CancellationSignal SIGNAL = new CancellationSignal();
70     private static final String MODE = "rw";
71     private static final ParcelFileDescriptor FD;
72     private static final AssetFileDescriptor ASSET_FD;
73     private static final Cursor CURSOR = new MatrixCursor(new String[0]);
74 
75     static {
76         try {
77             FD = ParcelFileDescriptor.open(new File("/dev/null"),
78                     ParcelFileDescriptor.MODE_READ_ONLY);
79             ASSET_FD = new AssetFileDescriptor(FD, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
80         } catch (Exception e) {
81             throw new RuntimeException(e);
82         }
83     }
84 
85     private Context mContext;
86     private ContentProvider mProvider;
87     private ContentResolver mResolver;
88 
89     @Before
setUp()90     public void setUp() throws Exception {
91         mContext = mock(Context.class, RETURNS_DEFAULTS);
92         mProvider = mock(ContentProvider.class, CALLS_REAL_METHODS);
93 
94         final ProviderInfo pi = new ProviderInfo();
95         pi.authority = AUTHORITY;
96         pi.exported = true;
97         mProvider.attachInfo(mContext, pi);
98 
99         mResolver = ContentResolver.wrap(mProvider);
100     }
101 
102     @Test
testApplyBatch()103     public void testApplyBatch() throws Exception {
104         doReturn(RESULTS).when(mProvider).applyBatch(AUTHORITY, OPERATIONS);
105         assertEquals(RESULTS, mResolver.applyBatch(AUTHORITY, OPERATIONS));
106     }
107 
108     @Test
testBulkInsert()109     public void testBulkInsert() throws Exception {
110         doReturn(42).when(mProvider).bulkInsert(URI, VALUES_ARRAY);
111         assertEquals(42, mResolver.bulkInsert(URI, VALUES_ARRAY));
112     }
113 
114     @Test
testCall()115     public void testCall() throws Exception {
116         doReturn(EXTRAS).when(mProvider).call(AUTHORITY, METHOD, ARG, EXTRAS);
117         assertEquals(EXTRAS, mResolver.call(AUTHORITY, METHOD, ARG, EXTRAS));
118         assertEquals(EXTRAS, mResolver.call(URI, METHOD, ARG, EXTRAS));
119     }
120 
121     @Test
testCanonicalize()122     public void testCanonicalize() throws Exception {
123         doReturn(URI).when(mProvider).canonicalize(URI);
124         assertEquals(URI, mResolver.canonicalize(URI));
125     }
126 
127     @Test
testUncanonicalize()128     public void testUncanonicalize() throws Exception {
129         doReturn(URI).when(mProvider).uncanonicalize(URI);
130         assertEquals(URI, mResolver.uncanonicalize(URI));
131     }
132 
133     @Test
testType()134     public void testType() throws Exception {
135         doReturn(TYPE).when(mProvider).getType(URI);
136         assertEquals(TYPE, mResolver.getType(URI));
137     }
138 
139     @Test
testStreamTypes()140     public void testStreamTypes() throws Exception {
141         doReturn(TYPE_ARRAY).when(mProvider).getStreamTypes(URI, TYPE);
142         assertEquals(TYPE_ARRAY, mResolver.getStreamTypes(URI, TYPE));
143     }
144 
145     @Test
testInsert()146     public void testInsert() throws Exception {
147         doReturn(URI).when(mProvider).insert(URI, VALUES);
148         assertEquals(URI, mResolver.insert(URI, VALUES));
149     }
150 
151     @Test
testUpdate()152     public void testUpdate() throws Exception {
153         doReturn(42).when(mProvider).update(URI, VALUES, ARG, ARG_ARRAY);
154         assertEquals(42, mResolver.update(URI, VALUES, ARG, ARG_ARRAY));
155     }
156 
157     @Test
testDelete()158     public void testDelete() throws Exception {
159         doReturn(42).when(mProvider).delete(URI, ARG, ARG_ARRAY);
160         assertEquals(42, mResolver.delete(URI, ARG, ARG_ARRAY));
161     }
162 
163     @Test
testRefresh()164     public void testRefresh() throws Exception {
165         doReturn(true).when(mProvider).refresh(URI, EXTRAS, SIGNAL);
166         assertEquals(true, mResolver.refresh(URI, EXTRAS, SIGNAL));
167     }
168 
169     @Test
testOpenAssetFile()170     public void testOpenAssetFile() throws Exception {
171         doReturn(ASSET_FD).when(mProvider).openAssetFile(URI, MODE, null);
172         assertEquals(ASSET_FD, mResolver.openAssetFile(URI, MODE, null));
173         assertEquals(ASSET_FD, mResolver.openAssetFileDescriptor(URI, MODE));
174         assertEquals(ASSET_FD, mResolver.openAssetFileDescriptor(URI, MODE, null));
175     }
176 
177     @Test
testOpenFile()178     public void testOpenFile() throws Exception {
179         doReturn(FD).when(mProvider).openFile(URI, MODE, null);
180         assertEquals(FD, mResolver.openFile(URI, MODE, null));
181         assertEquals(FD, mResolver.openFileDescriptor(URI, MODE));
182         assertEquals(FD, mResolver.openFileDescriptor(URI, MODE, null));
183     }
184 
185     @Test
testOpenStream()186     public void testOpenStream() throws Exception {
187         doReturn(ASSET_FD).when(mProvider).openAssetFile(URI, "r", null);
188         doReturn(ASSET_FD).when(mProvider).openAssetFile(URI, "w", null);
189         assertNotNull(mResolver.openInputStream(URI));
190         assertNotNull(mResolver.openOutputStream(URI));
191     }
192 
193     @Test
testOpenTypedAssetFile()194     public void testOpenTypedAssetFile() throws Exception {
195         doReturn(ASSET_FD).when(mProvider).openTypedAssetFile(URI, TYPE, EXTRAS, null);
196         assertEquals(ASSET_FD, mResolver.openTypedAssetFile(URI, TYPE, EXTRAS, null));
197         assertEquals(ASSET_FD, mResolver.openTypedAssetFileDescriptor(URI, TYPE, EXTRAS));
198         assertEquals(ASSET_FD, mResolver.openTypedAssetFileDescriptor(URI, TYPE, EXTRAS, null));
199     }
200 
201     @Test
testQuery()202     public void testQuery() throws Exception {
203         doReturn(CURSOR).when(mProvider).query(eq(URI), eq(ARG_ARRAY), any(), any());
204         assertEquals(CURSOR, mResolver.query(URI, ARG_ARRAY, null, null));
205         assertEquals(CURSOR, mResolver.query(URI, ARG_ARRAY, null, null, null));
206         assertEquals(CURSOR, mResolver.query(URI, ARG_ARRAY, null, null, null, null));
207     }
208 
209     @Test
testLoadThumbnail()210     public void testLoadThumbnail() throws Exception {
211         doReturn(ASSET_FD).when(mProvider).openTypedAssetFile(eq(URI), any(), any(), eq(SIGNAL));
212         try {
213             mResolver.loadThumbnail(URI, new Size(32, 32), SIGNAL);
214             fail();
215         } catch (IOException expected) {
216         }
217     }
218 }
219