Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: sync/test/android/javatests/src/org/chromium/sync/test/util/MockAccountManager.java

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.sync.test.util;
6
7 import android.accounts.Account;
8 import android.accounts.AccountManager;
9 import android.accounts.AuthenticatorDescription;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.os.AsyncTask;
13
14 import org.chromium.base.Callback;
15 import org.chromium.base.Log;
16 import org.chromium.base.VisibleForTesting;
17 import org.chromium.sync.signin.AccountManagerDelegate;
18 import org.chromium.sync.signin.AccountManagerHelper;
19
20 import java.util.ArrayList;
21 import java.util.HashSet;
22 import java.util.Set;
23 import java.util.UUID;
24 import java.util.concurrent.LinkedBlockingDeque;
25 import java.util.concurrent.ThreadPoolExecutor;
26 import java.util.concurrent.TimeUnit;
27
28 /**
29 * The MockAccountManager helps out if you want to mock out all calls to the And roid AccountManager.
30 *
31 * You should provide a set of accounts as a constructor argument, or use the mo re direct approach
32 * and provide an array of AccountHolder objects.
33 *
34 * Currently, this implementation supports adding and removing accounts, handlin g credentials
35 * (including confirming them), and handling of dummy auth tokens.
36 *
37 * If you want to auto-approve a given authtokentype, use addAccountHolderExplic itly(...) with
38 * an AccountHolder you have built with hasBeenAccepted("yourAuthTokenType", tru e).
39 *
40 * If you want to auto-approve all auth token types for a given account, use the {@link
41 * AccountHolder} builder method alwaysAccept(true).
42 */
43 public class MockAccountManager implements AccountManagerDelegate {
44
45 private static final String TAG = "MockAccountManager";
46
47 protected final Context mContext;
48
49 private final Set<AccountHolder> mAccounts;
50
51 // Tracks the number of in-progress getAccountsByType() tasks so that tests can wait for
52 // their completion.
53 private final ZeroCounter mGetAccountsTaskCounter;
54
55 @VisibleForTesting
56 public MockAccountManager(Context context, Context testContext, Account... a ccounts) {
57 mContext = context;
58 mGetAccountsTaskCounter = new ZeroCounter();
59 mAccounts = new HashSet<AccountHolder>();
60 if (accounts != null) {
61 for (Account account : accounts) {
62 mAccounts.add(AccountHolder.create().account(account).alwaysAcce pt(true).build());
63 }
64 }
65 }
66
67 private static class SingleThreadedExecutor extends ThreadPoolExecutor {
68 public SingleThreadedExecutor() {
69 super(1, 1, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>() );
70 }
71 }
72
73 @Override
74 public Account[] getAccountsByType(String type) {
75 if (!AccountManagerHelper.GOOGLE_ACCOUNT_TYPE.equals(type)) {
76 throw new IllegalArgumentException("Invalid account type: " + type);
77 }
78 if (mAccounts == null) {
79 return new Account[0];
80 } else {
81 ArrayList<Account> validAccounts = new ArrayList<Account>();
82 for (AccountHolder ah : mAccounts) {
83 if (type.equals(ah.getAccount().type)) {
84 validAccounts.add(ah.getAccount());
85 }
86 }
87
88 Account[] accounts = new Account[validAccounts.size()];
89 int i = 0;
90 for (Account account : validAccounts) {
91 accounts[i++] = account;
92 }
93 return accounts;
94 }
95 }
96
97 @Override
98 public void getAccountsByType(final String type, final Callback<Account[]> c allback) {
99 mGetAccountsTaskCounter.increment();
100 new AsyncTask<Void, Void, Account[]>() {
101 @Override
102 protected Account[] doInBackground(Void... params) {
103 return getAccountsByType(type);
104 }
105
106 @Override
107 protected void onPostExecute(Account[] accounts) {
108 callback.onResult(accounts);
109 mGetAccountsTaskCounter.decrement();
110 }
111 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
112 }
113
114 @VisibleForTesting
115 public void waitForGetAccountsTask() throws InterruptedException {
116 // Wait until all tasks are done because we don't know which is being wa ited for.
117 mGetAccountsTaskCounter.waitUntilZero();
118 }
119
120 @VisibleForTesting
121 public boolean addAccountHolderExplicitly(AccountHolder accountHolder) {
122 return addAccountHolderExplicitly(accountHolder, false);
123 }
124
125 /**
126 * Add an AccountHolder directly.
127 *
128 * @param accountHolder the account holder to add
129 * @param broadcastEvent whether to broadcast an AccountChangedEvent
130 * @return whether the account holder was added successfully
131 */
132 public boolean addAccountHolderExplicitly(AccountHolder accountHolder,
133 boolean broadcastEvent) {
134 boolean result = mAccounts.add(accountHolder);
135 if (broadcastEvent) {
136 postAsyncAccountChangedEvent();
137 }
138 return result;
139 }
140
141 @VisibleForTesting
142 public boolean removeAccountHolderExplicitly(AccountHolder accountHolder) {
143 return removeAccountHolderExplicitly(accountHolder, false);
144 }
145
146 /**
147 * Remove an AccountHolder directly.
148 *
149 * @param accountHolder the account holder to remove
150 * @param broadcastEvent whether to broadcast an AccountChangedEvent
151 * @return whether the account holder was removed successfully
152 */
153 public boolean removeAccountHolderExplicitly(AccountHolder accountHolder,
154 boolean broadcastEvent) {
155 boolean result = mAccounts.remove(accountHolder);
156 if (broadcastEvent) {
157 postAsyncAccountChangedEvent();
158 }
159 return result;
160 }
161
162 @Override
163 public String getAuthToken(Account account, String authTokenScope) {
164 AccountHolder ah = getAccountHolder(account);
165 assert ah.hasBeenAccepted(authTokenScope);
166 synchronized (mAccounts) {
167 // Some tests register auth tokens with value null, and those should be preserved.
168 if (!ah.hasAuthTokenRegistered(authTokenScope)
169 && ah.getAuthToken(authTokenScope) == null) {
170 // No authtoken registered. Need to create one.
171 String authToken = UUID.randomUUID().toString();
172 Log.d(TAG, "Created new auth token for " + ah.getAccount() + ": authTokenScope = "
173 + authTokenScope + ", authToken = " + authToken) ;
174 ah = ah.withAuthToken(authTokenScope, authToken);
175 mAccounts.add(ah);
176 }
177 }
178 return ah.getAuthToken(authTokenScope);
179 }
180
181 @Override
182 public void invalidateAuthToken(String authToken) {
183 if (authToken == null) {
184 throw new IllegalArgumentException("AuthToken can not be null");
185 }
186 for (AccountHolder ah : mAccounts) {
187 if (ah.removeAuthToken(authToken)) {
188 break;
189 }
190 }
191 }
192
193 @Override
194 public AuthenticatorDescription[] getAuthenticatorTypes() {
195 AuthenticatorDescription googleAuthenticator = new AuthenticatorDescript ion(
196 AccountManagerHelper.GOOGLE_ACCOUNT_TYPE, "p1", 0, 0, 0, 0);
197
198 return new AuthenticatorDescription[] { googleAuthenticator };
199 }
200
201 @Override
202 public void hasFeatures(
203 Account account, final String[] features, final Callback<Boolean> ca llback) {
204 final AccountHolder accountHolder = getAccountHolder(account);
205 accountHolder.addFeaturesCallback(new Runnable() {
206 @Override
207 public void run() {
208 Set<String> accountFeatures = accountHolder.getFeatures();
209 boolean hasAllFeatures = true;
210 for (String feature : features) {
211 if (!accountFeatures.contains(feature)) {
212 Log.d(TAG, accountFeatures + " does not contain " + feat ure);
213 hasAllFeatures = false;
214 }
215 }
216 callback.onResult(hasAllFeatures);
217 }
218 });
219 }
220
221 private AccountHolder getAccountHolder(Account account) {
222 if (account == null) {
223 throw new IllegalArgumentException("Account can not be null");
224 }
225 for (AccountHolder accountHolder : mAccounts) {
226 if (account.equals(accountHolder.getAccount())) {
227 return accountHolder;
228 }
229 }
230 throw new IllegalArgumentException("Can not find AccountHolder for accou nt " + account);
231 }
232
233 private void postAsyncAccountChangedEvent() {
234 // Mimic that this does not happen on the main thread.
235 new AsyncTask<Void, Void, Void>() {
236 @Override
237 protected Void doInBackground(Void... params) {
238 mContext.sendBroadcast(new Intent(AccountManager.LOGIN_ACCOUNTS_ CHANGED_ACTION));
239 return null;
240 }
241 }.execute();
242 }
243
244 /**
245 * Simple concurrency helper class for waiting until a resource count become s zero.
246 */
247 private static class ZeroCounter {
248 private static final int WAIT_TIMEOUT_MS = 10000;
249
250 private final Object mLock = new Object();
251 private int mCount = 0;
252
253 public void increment() {
254 synchronized (mLock) {
255 mCount++;
256 }
257 }
258
259 public void decrement() {
260 synchronized (mLock) {
261 if (--mCount == 0) {
262 mLock.notifyAll();
263 }
264 }
265 }
266
267 public void waitUntilZero() throws InterruptedException {
268 synchronized (mLock) {
269 while (mCount != 0) {
270 mLock.wait(WAIT_TIMEOUT_MS);
271 }
272 }
273 }
274 }
275 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698