AccountsDbTest.java revision e5768621de9a41eb7b5449b6aa5a7a9579682a0a
1
2/*
3 * Copyright (C) 2016 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License
16 */
17
18package com.android.server.accounts;
19
20import android.accounts.Account;
21import android.content.Context;
22import android.database.Cursor;
23import android.support.test.InstrumentationRegistry;
24import android.support.test.runner.AndroidJUnit4;
25import android.test.suitebuilder.annotation.SmallTest;
26import android.util.Pair;
27
28import org.junit.After;
29import org.junit.Before;
30import org.junit.Test;
31import org.junit.runner.RunWith;
32
33import java.io.File;
34import java.util.Arrays;
35import java.util.List;
36import java.util.Map;
37
38import static org.junit.Assert.assertEquals;
39import static org.junit.Assert.assertFalse;
40import static org.junit.Assert.assertNull;
41import static org.junit.Assert.assertTrue;
42
43/**
44 * Tests for {@link AccountsDb}.
45 * <p>Run with:<pre>
46 * m FrameworksServicesTests &&
47 * adb install \
48 * -r out/target/product/marlin/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
49 * adb shell am instrument -e class com.android.server.accounts.AccountsDbTest \
50 * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
51 * </pre>
52 */
53@RunWith(AndroidJUnit4.class)
54@SmallTest
55public class AccountsDbTest {
56    private static final String PREN_DB = "pren.db";
57    private static final String DE_DB = "de.db";
58    private static final String CE_DB = "ce.db";
59
60    private AccountsDb mAccountsDb;
61    private File preNDb;
62    private File deDb;
63    private File ceDb;
64
65    @Before
66    public void setUp() {
67        Context context = InstrumentationRegistry.getContext();
68        preNDb = new File(context.getCacheDir(), PREN_DB);
69        ceDb = new File(context.getCacheDir(), CE_DB);
70        deDb = new File(context.getCacheDir(), DE_DB);
71        deleteDbFiles();
72        mAccountsDb = AccountsDb.create(context, 0, preNDb, deDb);
73    }
74
75    @After
76    public void tearDown() {
77        deleteDbFiles();
78    }
79
80    private void deleteDbFiles() {
81        AccountsDb.deleteDbFileWarnIfFailed(preNDb);
82        AccountsDb.deleteDbFileWarnIfFailed(ceDb);
83        AccountsDb.deleteDbFileWarnIfFailed(deDb);
84    }
85
86    @Test
87    public void testCeNotAvailableInitially() {
88        Account account = new Account("name", "example.com");
89        long id = mAccountsDb.insertCeAccount(account, "");
90        assertEquals("Insert into CE should fail until CE database is attached", -1, id);
91    }
92
93    @Test
94    public void testDeAccountInsertFindDelete() {
95        Account account = new Account("name", "example.com");
96        long accId = 1;
97        mAccountsDb.insertDeAccount(account, accId);
98        long actualId = mAccountsDb.findDeAccountId(account);
99        assertEquals(accId, actualId);
100        // Delete and verify that account no longer exists
101        mAccountsDb.deleteDeAccount(accId);
102        actualId = mAccountsDb.findDeAccountId(account);
103        assertEquals(-1, actualId);
104    }
105
106    @Test
107    public void testCeAccountInsertFindDelete() {
108        mAccountsDb.attachCeDatabase(ceDb);
109        Account account = new Account("name", "example.com");
110        long accId = mAccountsDb.insertCeAccount(account, "password");
111        long actualId = mAccountsDb.findCeAccountId(account);
112        assertEquals(accId, actualId);
113        // Delete and verify that account no longer exists
114        mAccountsDb.deleteCeAccount(accId);
115        actualId = mAccountsDb.findCeAccountId(account);
116        assertEquals(-1, actualId);
117    }
118
119    @Test
120    public void testAuthTokenInsertFindDelete() {
121        mAccountsDb.attachCeDatabase(ceDb);
122        Account account = new Account("name", "example.com");
123        long accId = mAccountsDb.insertCeAccount(account, "password");
124        mAccountsDb.insertDeAccount(account, accId);
125        long authTokenId = mAccountsDb.insertAuthToken(accId, "type", "token");
126        Map<String, String> authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
127        assertEquals(1, authTokensByAccount.size());
128        try (Cursor cursor = mAccountsDb.findAuthtokenForAllAccounts(account.type, "token")) {
129            assertTrue(cursor.moveToNext());
130        }
131        try (Cursor cursor = mAccountsDb.findAuthtokenForAllAccounts(account.type, "nosuchtoken")) {
132            assertFalse(cursor.moveToNext());
133        }
134        mAccountsDb.deleteAuthToken(String.valueOf(authTokenId));
135        // Verify that token no longer exists
136        authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
137        assertEquals(0, authTokensByAccount.size());
138    }
139
140    @Test
141    public void testAuthTokenDeletes() {
142        mAccountsDb.attachCeDatabase(ceDb);
143        // 1st account
144        Account account = new Account("name", "example.com");
145        long accId = mAccountsDb.insertCeAccount(account, "password");
146        mAccountsDb.insertDeAccount(account, accId);
147        mAccountsDb.insertAuthToken(accId, "type", "token");
148        mAccountsDb.insertAuthToken(accId, "type2", "token2");
149        // 2nd account
150        Account account2 = new Account("name", "example2.com");
151        long accId2 = mAccountsDb.insertCeAccount(account2, "password");
152        mAccountsDb.insertDeAccount(account2, accId);
153        mAccountsDb.insertAuthToken(accId2, "type", "token");
154
155        mAccountsDb.deleteAuthTokensByAccountId(accId2);
156        Map<String, String> authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account2);
157        assertEquals(0, authTokensByAccount.size());
158        // Authtokens from account 1 are still there
159        authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
160        assertEquals(2, authTokensByAccount.size());
161
162        // Delete authtokens from account 1 and verify
163        mAccountsDb.deleteAuthtokensByAccountIdAndType(accId, "type");
164        authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
165        assertEquals(1, authTokensByAccount.size());
166        mAccountsDb.deleteAuthtokensByAccountIdAndType(accId, "type2");
167        authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
168        assertEquals(0, authTokensByAccount.size());
169    }
170
171    @Test
172    public void testExtrasInsertFindDelete() {
173        mAccountsDb.attachCeDatabase(ceDb);
174        Account account = new Account("name", "example.com");
175        long accId = mAccountsDb.insertCeAccount(account, "password");
176        mAccountsDb.insertDeAccount(account, accId);
177        String extraKey = "extra_key";
178        String extraValue = "extra_value";
179        long extraId = mAccountsDb.insertExtra(accId, extraKey, extraValue);
180        // Test find methods
181        long actualExtraId = mAccountsDb.findExtrasIdByAccountId(accId, extraKey);
182        assertEquals(extraId, actualExtraId);
183        Map<String, String> extras = mAccountsDb.findUserExtrasForAccount(account);
184        assertEquals(1, extras.size());
185        assertEquals(extraValue, extras.get(extraKey));
186        // Test update
187        String newExtraValue = "extra_value2";
188        mAccountsDb.updateExtra(extraId, newExtraValue);
189        String newValue = mAccountsDb.findUserExtrasForAccount(account).get(extraKey);
190        assertEquals(newExtraValue, newValue);
191
192        // Delete account and verify that extras cascade removed
193        mAccountsDb.deleteCeAccount(accId);
194        actualExtraId = mAccountsDb.findExtrasIdByAccountId(accId, extraKey);
195        assertEquals(-1, actualExtraId);
196    }
197
198    @Test
199    public void testGrantsInsertFindDelete() {
200        mAccountsDb.attachCeDatabase(ceDb);
201        Account account = new Account("name", "example.com");
202        long accId = mAccountsDb.insertCeAccount(account, "password");
203        mAccountsDb.insertDeAccount(account, accId);
204        int testUid = 100500;
205        long grantId = mAccountsDb.insertGrant(accId, "tokenType", testUid);
206        assertTrue(grantId > 0);
207        List<Integer> allUidGrants = mAccountsDb.findAllUidGrants();
208        List<Integer> expectedUids = Arrays.asList(testUid);
209        assertEquals(expectedUids, allUidGrants);
210
211        long matchingGrantsCount = mAccountsDb.findMatchingGrantsCount(
212                testUid, "tokenType", account);
213        assertEquals(1, matchingGrantsCount);
214        // Test nonexistent type
215        matchingGrantsCount = mAccountsDb.findMatchingGrantsCount(
216                testUid, "noSuchType", account);
217        assertEquals(0, matchingGrantsCount);
218
219        matchingGrantsCount = mAccountsDb.findMatchingGrantsCountAnyToken(testUid, account);
220        assertEquals(1, matchingGrantsCount);
221
222        List<Pair<String, Integer>> allAccountGrants = mAccountsDb.findAllAccountGrants();
223        assertEquals(1, allAccountGrants.size());
224        assertEquals(account.name, allAccountGrants.get(0).first);
225        assertEquals(testUid, (int)allAccountGrants.get(0).second);
226
227        mAccountsDb.deleteGrantsByUid(testUid);
228        allUidGrants = mAccountsDb.findAllUidGrants();
229        assertTrue("Test grants should be removed", allUidGrants.isEmpty());
230    }
231
232    @Test
233    public void testSharedAccountsInsertFindDelete() {
234        Account account = new Account("name", "example.com");
235        long accId = 0;
236        mAccountsDb.insertDeAccount(account, accId);
237        long sharedAccId = mAccountsDb.insertSharedAccount(account);
238        long foundSharedAccountId = mAccountsDb.findSharedAccountId(account);
239        assertEquals(sharedAccId, foundSharedAccountId);
240        List<Account> sharedAccounts = mAccountsDb.getSharedAccounts();
241        List<Account> expectedList = Arrays.asList(account);
242        assertEquals(expectedList, sharedAccounts);
243
244        // Delete and verify
245        mAccountsDb.deleteSharedAccount(account);
246        foundSharedAccountId = mAccountsDb.findSharedAccountId(account);
247        assertEquals(-1, foundSharedAccountId);
248    }
249
250    @Test
251    public void testMetaInsertFindDelete() {
252        int testUid = 100500;
253        String authenticatorType = "authType";
254        mAccountsDb.insertOrReplaceMetaAuthTypeAndUid(authenticatorType, testUid);
255        Map<String, Integer> metaAuthUid = mAccountsDb.findMetaAuthUid();
256        assertEquals(1, metaAuthUid.size());
257        assertEquals(testUid, (int)metaAuthUid.get(authenticatorType));
258
259        // Delete and verify
260        boolean deleteResult = mAccountsDb.deleteMetaByAuthTypeAndUid(authenticatorType, testUid);
261        assertTrue(deleteResult);
262        metaAuthUid = mAccountsDb.findMetaAuthUid();
263        assertEquals(0, metaAuthUid.size());
264    }
265
266    @Test
267    public void testUpdateDeAccountLastAuthenticatedTime() {
268        Account account = new Account("name", "example.com");
269        long accId = 1;
270        mAccountsDb.insertDeAccount(account, accId);
271        long now = System.currentTimeMillis();
272        mAccountsDb.updateAccountLastAuthenticatedTime(account);
273        long time = mAccountsDb.findAccountLastAuthenticatedTime(account);
274        assertTrue("LastAuthenticatedTime should be current", time >= now);
275    }
276
277    @Test
278    public void testRenameAccount() {
279        mAccountsDb.attachCeDatabase(ceDb);
280        Account account = new Account("name", "example.com");
281        long accId = mAccountsDb.insertCeAccount(account, "password");
282        mAccountsDb.insertDeAccount(account, accId);
283        mAccountsDb.renameDeAccount(accId, "newName", "name");
284        Account newAccount = mAccountsDb.findAllDeAccounts().get(accId);
285        assertEquals("newName", newAccount.name);
286
287        String prevName = mAccountsDb.findDeAccountPreviousName(newAccount);
288        assertEquals("name", prevName);
289        mAccountsDb.renameCeAccount(accId, "newName");
290        long foundAccId = mAccountsDb.findCeAccountId(account);
291        assertEquals("Account shouldn't be found under the old name", -1, foundAccId);
292        foundAccId = mAccountsDb.findCeAccountId(newAccount);
293        assertEquals(accId, foundAccId);
294    }
295
296    @Test
297    public void testUpdateCeAccountPassword() {
298        mAccountsDb.attachCeDatabase(ceDb);
299        Account account = new Account("name", "example.com");
300        long accId = mAccountsDb.insertCeAccount(account, "password");
301        String newPassword = "newPassword";
302        mAccountsDb.updateCeAccountPassword(accId, newPassword);
303        String actualPassword = mAccountsDb
304                .findAccountPasswordByNameAndType(account.name, account.type);
305        assertEquals(newPassword, actualPassword);
306    }
307
308    @Test
309    public void testFindCeAccountsNotInDe() {
310        mAccountsDb.attachCeDatabase(ceDb);
311        Account account = new Account("name", "example.com");
312        long accId = mAccountsDb.insertCeAccount(account, "password");
313        mAccountsDb.insertDeAccount(account, accId);
314
315        Account accountNotInDe = new Account("name2", "example.com");
316        mAccountsDb.insertCeAccount(accountNotInDe, "password");
317
318        List<Account> ceAccounts = mAccountsDb.findCeAccountsNotInDe();
319        List<Account> expectedList = Arrays.asList(accountNotInDe);
320        assertEquals(expectedList, ceAccounts);
321    }
322
323    @Test
324    public void testCrossDbTransactions() {
325        mAccountsDb.attachCeDatabase(ceDb);
326        mAccountsDb.beginTransaction();
327        Account account = new Account("name", "example.com");
328        long accId;
329        accId = mAccountsDb.insertCeAccount(account, "password");
330        accId = mAccountsDb.insertDeAccount(account, accId);
331        long actualId = mAccountsDb.findCeAccountId(account);
332        assertEquals(accId, actualId);
333        actualId = mAccountsDb.findDeAccountId(account);
334        assertEquals(accId, actualId);
335        mAccountsDb.endTransaction();
336        // Verify that records were removed
337        actualId = mAccountsDb.findCeAccountId(account);
338        assertEquals(-1, actualId);
339        actualId = mAccountsDb.findDeAccountId(account);
340        assertEquals(-1, actualId);
341    }
342
343    @Test
344    public void testFindDeAccountByAccountId() {
345        long accId = 10;
346        Account account = new Account("name", "example.com");
347        assertNull(mAccountsDb.findDeAccountByAccountId(accId));
348
349        mAccountsDb.insertDeAccount(account, accId);
350
351        Account foundAccount = mAccountsDb.findDeAccountByAccountId(accId);
352        assertEquals(account, foundAccount);
353    }
354
355    @Test
356    public void testVisibilityFindSetDelete() {
357        long accId = 10;
358        int uid1 = 100500;
359        int uid2 = 100501;
360        Account account = new Account("name", "example.com");
361        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
362
363        mAccountsDb.insertDeAccount(account, accId);
364        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
365        assertNull(mAccountsDb.findAccountVisibility(accId, uid1));
366
367        mAccountsDb.setAccountVisibility(accId, uid1, 1);
368        assertEquals(mAccountsDb.findAccountVisibility(account, uid1), Integer.valueOf(1));
369        assertEquals(mAccountsDb.findAccountVisibility(accId, uid1), Integer.valueOf(1));
370
371        mAccountsDb.setAccountVisibility(accId, uid2, 2);
372        assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(2));
373
374        mAccountsDb.setAccountVisibility(accId, uid2, 3);
375        assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(3));
376
377        Map<Integer, Integer> vis = mAccountsDb.findAccountVisibilityForAccountId(accId);
378        assertEquals(vis.size(), 2);
379        assertEquals(vis.get(uid1), Integer.valueOf(1));
380        assertEquals(vis.get(uid2), Integer.valueOf(3));
381
382        assertTrue(mAccountsDb.deleteAccountVisibilityForUid(uid1));
383        assertNull(mAccountsDb.findAccountVisibility(accId, uid1));
384        assertFalse(mAccountsDb.deleteAccountVisibilityForUid(uid1)); // Already deleted.
385    }
386
387    @Test
388    public void testVisibilityCleanupTrigger() {
389        long accId = 10;
390        int uid1 = 100500;
391        Account account = new Account("name", "example.com");
392
393        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
394        mAccountsDb.insertDeAccount(account, accId);
395        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
396
397        mAccountsDb.setAccountVisibility(accId, uid1, 1);
398        assertEquals(mAccountsDb.findAccountVisibility(accId, uid1), Integer.valueOf(1));
399
400        assertTrue(mAccountsDb.deleteDeAccount(accId)); // Trigger should remove visibility.
401        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
402    }
403}
404