EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.sync.test.util]

COVERAGE SUMMARY FOR SOURCE FILE [MockSyncContentResolverDelegate.java]

nameclass, %method, %block, %line, %
MockSyncContentResolverDelegate.java75%  (3/4)95%  (19/20)73%  (286/393)80%  (59.3/74)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MockSyncContentResolverDelegate100% (1/1)92%  (11/12)68%  (230/337)76%  (46.3/61)
removeStatusChangeListener (Object): void 0%   (0/1)0%   (0/19)0%   (0/4)
setIsSyncable (Account, String, int): void 100% (1/1)47%  (30/64)61%  (8/13)
setSyncAutomatically (Account, String, boolean): void 100% (1/1)56%  (35/63)82%  (7.4/9)
addStatusChangeListener (int, SyncStatusObserver): Object 100% (1/1)71%  (24/34)83%  (5.8/7)
getSyncAutomatically (Account, String): boolean 100% (1/1)84%  (27/32)75%  (3/4)
getIsSyncable (Account, String): int 100% (1/1)85%  (28/33)83%  (5/6)
notifyObservers (): void 100% (1/1)88%  (35/40)90%  (5.4/6)
setMasterSyncAutomatically (boolean): void 100% (1/1)91%  (10/11)95%  (3.8/4)
MockSyncContentResolverDelegate (): void 100% (1/1)100% (13/13)100% (4/4)
createKey (Account, String): String 100% (1/1)100% (17/17)100% (1/1)
getMasterSyncAutomatically (): boolean 100% (1/1)100% (3/3)100% (1/1)
waitForLastNotificationCompleted (): void 100% (1/1)100% (8/8)100% (2/2)
     
class MockSyncContentResolverDelegate$10%   (0/1)100% (0/0)100% (0/0)100% (0/0)
     
class MockSyncContentResolverDelegate$AsyncSyncStatusObserver100% (1/1)100% (5/5)100% (36/36)100% (9/9)
MockSyncContentResolverDelegate$AsyncSyncStatusObserver (SyncStatusObserver):... 100% (1/1)100% (6/6)100% (3/3)
MockSyncContentResolverDelegate$AsyncSyncStatusObserver (SyncStatusObserver, ... 100% (1/1)100% (4/4)100% (1/1)
access$100 (MockSyncContentResolverDelegate$AsyncSyncStatusObserver, Semaphor... 100% (1/1)100% (4/4)100% (1/1)
access$200 (MockSyncContentResolverDelegate$AsyncSyncStatusObserver): SyncSta... 100% (1/1)100% (3/3)100% (1/1)
notifyObserverAsync (Semaphore): void 100% (1/1)100% (19/19)100% (5/5)
     
class MockSyncContentResolverDelegate$AsyncSyncStatusObserver$1100% (1/1)100% (3/3)100% (20/20)100% (5/5)
MockSyncContentResolverDelegate$AsyncSyncStatusObserver$1 (MockSyncContentRes... 100% (1/1)100% (9/9)100% (1/1)
doInBackground (Void []): Void 100% (1/1)100% (7/7)100% (2/2)
onPostExecute (Void): void 100% (1/1)100% (4/4)100% (2/2)

1// Copyright (c) 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 
5package org.chromium.sync.test.util;
6 
7 
8import android.accounts.Account;
9import android.content.ContentResolver;
10import android.content.SyncStatusObserver;
11import android.os.AsyncTask;
12 
13import junit.framework.Assert;
14 
15import org.chromium.base.ThreadUtils;
16import org.chromium.sync.notifier.SyncContentResolverDelegate;
17 
18import java.util.HashMap;
19import java.util.HashSet;
20import java.util.Map;
21import java.util.Set;
22import java.util.concurrent.Semaphore;
23import java.util.concurrent.TimeUnit;
24 
25 
26/**
27 * Mock implementation of the SyncContentResolverWrapper.
28 *
29 * This implementation only supports status change listeners for the type
30 * SYNC_OBSERVER_TYPE_SETTINGS.
31 */
32public class MockSyncContentResolverDelegate implements SyncContentResolverDelegate {
33 
34    private final Map<String, Boolean> mSyncAutomaticallyMap;
35 
36    private final Set<AsyncSyncStatusObserver> mObservers;
37 
38    private boolean mMasterSyncAutomatically;
39 
40    private Semaphore mPendingObserverCount;
41 
42    public MockSyncContentResolverDelegate() {
43        mSyncAutomaticallyMap = new HashMap<String, Boolean>();
44        mObservers = new HashSet<AsyncSyncStatusObserver>();
45    }
46 
47    @Override
48    public Object addStatusChangeListener(int mask, SyncStatusObserver callback) {
49        if (mask != ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS) {
50            throw new IllegalArgumentException("This implementation only supports "
51                    + "ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS as the mask");
52        }
53        AsyncSyncStatusObserver asyncSyncStatusObserver = new AsyncSyncStatusObserver(callback);
54        synchronized (mObservers) {
55            mObservers.add(asyncSyncStatusObserver);
56        }
57        return asyncSyncStatusObserver;
58    }
59 
60    @Override
61    public void removeStatusChangeListener(Object handle) {
62        synchronized (mObservers) {
63            mObservers.remove(handle);
64        }
65    }
66 
67    @Override
68    public void setMasterSyncAutomatically(boolean sync) {
69        if (mMasterSyncAutomatically == sync) return;
70 
71        mMasterSyncAutomatically = sync;
72        notifyObservers();
73    }
74 
75    @Override
76    public boolean getMasterSyncAutomatically() {
77        return mMasterSyncAutomatically;
78    }
79 
80    @Override
81    public boolean getSyncAutomatically(Account account, String authority) {
82        String key = createKey(account, authority);
83        synchronized (mSyncAutomaticallyMap) {
84            return mSyncAutomaticallyMap.containsKey(key) && mSyncAutomaticallyMap.get(key);
85        }
86    }
87 
88    @Override
89    public void setSyncAutomatically(Account account, String authority, boolean sync) {
90        String key = createKey(account, authority);
91        synchronized (mSyncAutomaticallyMap) {
92            if (!mSyncAutomaticallyMap.containsKey(key)) {
93                throw new IllegalArgumentException("Account " + account +
94                        " is not syncable for authority " + authority +
95                        ". Can not set sync state to " + sync);
96            }
97            if (mSyncAutomaticallyMap.get(key) == sync) return;
98            mSyncAutomaticallyMap.put(key, sync);
99        }
100        notifyObservers();
101    }
102 
103    @Override
104    public void setIsSyncable(Account account, String authority, int syncable) {
105        String key = createKey(account, authority);
106 
107        synchronized (mSyncAutomaticallyMap) {
108            switch (syncable) {
109                case 0:
110                    if (!mSyncAutomaticallyMap.containsKey(key)) return;
111 
112                    mSyncAutomaticallyMap.remove(key);
113                    break;
114                case 1:
115                    if (mSyncAutomaticallyMap.containsKey(key)) return;
116 
117                    mSyncAutomaticallyMap.put(key, false);
118                    break;
119                default:
120                    throw new IllegalArgumentException("Unable to understand syncable argument: " +
121                            syncable);
122            }
123        }
124        notifyObservers();
125    }
126 
127    @Override
128    public int getIsSyncable(Account account, String authority) {
129        synchronized (mSyncAutomaticallyMap) {
130            final Boolean isSyncable = mSyncAutomaticallyMap.get(createKey(account, authority));
131            if (isSyncable == null) {
132                return -1;
133            }
134            return isSyncable ? 1 : 0;
135        }
136    }
137 
138    private static String createKey(Account account, String authority) {
139        return account.name + "@@@" + account.type + "@@@" + authority;
140    }
141 
142    private void notifyObservers() {
143        synchronized (mObservers) {
144            mPendingObserverCount = new Semaphore(1 - mObservers.size());
145            for (AsyncSyncStatusObserver observer : mObservers) {
146                observer.notifyObserverAsync(mPendingObserverCount);
147            }
148        }
149    }
150 
151    /**
152     * Blocks until the last notification has been issued to all registered observers.
153     * Note that if an observer is removed while a notification is being handled this can
154     * fail to return correctly.
155     *
156     * @throws InterruptedException
157     */
158    public void waitForLastNotificationCompleted() throws InterruptedException {
159        Assert.assertTrue("Timed out waiting for notifications to complete.",
160                mPendingObserverCount.tryAcquire(5, TimeUnit.SECONDS));
161    }
162 
163    private static class AsyncSyncStatusObserver {
164 
165        private final SyncStatusObserver mSyncStatusObserver;
166 
167        private AsyncSyncStatusObserver(SyncStatusObserver syncStatusObserver) {
168            mSyncStatusObserver = syncStatusObserver;
169        }
170 
171        private void notifyObserverAsync(final Semaphore pendingObserverCount) {
172            if (ThreadUtils.runningOnUiThread()) {
173                new AsyncTask<Void, Void, Void>() {
174                    @Override
175                    protected Void doInBackground(Void... params) {
176                        mSyncStatusObserver.onStatusChanged(
177                                ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
178                        return null;
179                    }
180 
181                    @Override
182                    protected void onPostExecute(Void result) {
183                        pendingObserverCount.release();
184                    }
185                }.execute();
186            } else {
187                mSyncStatusObserver.onStatusChanged(
188                        ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
189                pendingObserverCount.release();
190            }
191        }
192    }
193}

[all classes][org.chromium.sync.test.util]
EMMA 2.0.5312 (C) Vladimir Roubtsov