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

COVERAGE SUMMARY FOR SOURCE FILE [AwContentsTest.java]

nameclass, %method, %block, %line, %
AwContentsTest.java100% (10/10)97%  (36/37)93%  (756/811)97%  (155.4/160)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AwContentsTest$OnDownloadStartHelper100% (1/1)88%  (7/8)66%  (59/89)78%  (14/18)
getUserAgent (): String 0%   (0/1)0%   (0/12)0%   (0/2)
getContentDisposition (): String 100% (1/1)67%  (8/12)78%  (1.6/2)
getContentLength (): long 100% (1/1)67%  (8/12)78%  (1.6/2)
getMimeType (): String 100% (1/1)67%  (8/12)78%  (1.6/2)
getUrl (): String 100% (1/1)67%  (8/12)78%  (1.6/2)
<static initializer> 100% (1/1)75%  (6/8)75%  (0.8/1)
AwContentsTest$OnDownloadStartHelper (): void 100% (1/1)100% (3/3)100% (1/1)
notifyCalled (String, String, String, String, long): void 100% (1/1)100% (18/18)100% (7/7)
     
class AwContentsTest$1100% (1/1)100% (2/2)93%  (13/14)94%  (1.9/2)
call (): Boolean 100% (1/1)88%  (7/8)87%  (0.9/1)
AwContentsTest$1 (AwContentsTest): void 100% (1/1)100% (6/6)100% (1/1)
     
class AwContentsTest$3100% (1/1)100% (2/2)93%  (13/14)94%  (1.9/2)
call (): Boolean 100% (1/1)88%  (7/8)87%  (0.9/1)
AwContentsTest$3 (AwContentsTest): void 100% (1/1)100% (6/6)100% (1/1)
     
class AwContentsTest100% (1/1)100% (12/12)96%  (550/573)100% (122.6/123)
testGetFavicon (): void 100% (1/1)91%  (75/82)99%  (15.9/16)
testDownload (): void 100% (1/1)93%  (89/96)100% (21.9/22)
testClearCacheMemoryAndDisk (): void 100% (1/1)94%  (103/110)100% (20.9/21)
testCreateAndGcManyTimes (): void 100% (1/1)97%  (69/71)99%  (14.9/15)
AwContentsTest (): void 100% (1/1)100% (8/8)100% (2/2)
callDocumentHasImagesSync (AwContents): int 100% (1/1)100% (36/36)100% (7/7)
testClearCacheInQuickSuccession (): void 100% (1/1)100% (17/17)100% (4/4)
testCreateDestroy (): void 100% (1/1)100% (7/7)100% (2/2)
testCreateLoadDestroyManyAtOnce (): void 100% (1/1)100% (49/49)100% (9/9)
testCreateLoadDestroyManyTimes (): void 100% (1/1)100% (28/28)100% (7/7)
testCreateLoadPageDestroy (): void 100% (1/1)100% (22/22)100% (5/5)
testDocumentHasImages (): void 100% (1/1)100% (47/47)100% (13/13)
     
class AwContentsTest$2100% (1/1)100% (2/2)100% (12/12)100% (3/3)
AwContentsTest$2 (AwContentsTest): void 100% (1/1)100% (6/6)100% (1/1)
run (): void 100% (1/1)100% (6/6)100% (2/2)
     
class AwContentsTest$4100% (1/1)100% (2/2)100% (22/22)100% (4/4)
AwContentsTest$4 (AwContentsTest, Looper, AtomicInteger, Semaphore): void 100% (1/1)100% (13/13)100% (1/1)
handleMessage (Message): void 100% (1/1)100% (9/9)100% (3/3)
     
class AwContentsTest$5100% (1/1)100% (2/2)100% (18/18)100% (3/3)
AwContentsTest$5 (AwContentsTest, AwContents, Message): void 100% (1/1)100% (12/12)100% (1/1)
run (): void 100% (1/1)100% (6/6)100% (2/2)
     
class AwContentsTest$6100% (1/1)100% (2/2)100% (21/21)100% (4/4)
AwContentsTest$6 (AwContentsTest, AwContents): void 100% (1/1)100% (9/9)100% (1/1)
run (): void 100% (1/1)100% (12/12)100% (3/3)
     
class AwContentsTest$7100% (1/1)100% (2/2)100% (28/28)100% (2/2)
AwContentsTest$7 (AwContentsTest, AwContents, Bitmap): void 100% (1/1)100% (12/12)100% (1/1)
call (): Boolean 100% (1/1)100% (16/16)100% (1/1)
     
class AwContentsTest$TestAwContentsClient100% (1/1)100% (3/3)100% (20/20)100% (6/6)
AwContentsTest$TestAwContentsClient (): void 100% (1/1)100% (8/8)100% (3/3)
getOnDownloadStartHelper (): AwContentsTest$OnDownloadStartHelper 100% (1/1)100% (3/3)100% (1/1)
onDownloadStart (String, String, String, String, long): void 100% (1/1)100% (9/9)100% (2/2)

1// Copyright (c) 2012 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.android_webview.test;
6 
7import android.graphics.Bitmap;
8import android.graphics.BitmapFactory;
9import android.os.Handler;
10import android.os.Looper;
11import android.os.Message;
12import android.test.UiThreadTest;
13import android.test.suitebuilder.annotation.LargeTest;
14import android.test.suitebuilder.annotation.SmallTest;
15import android.util.Pair;
16 
17import org.chromium.android_webview.AwContents;
18import org.chromium.android_webview.test.util.CommonResources;
19import org.chromium.base.test.util.DisabledTest;
20import org.chromium.base.test.util.Feature;
21import org.chromium.content.browser.test.util.CallbackHelper;
22import org.chromium.net.test.util.TestWebServer;
23 
24import java.io.InputStream;
25import java.net.URL;
26import java.util.ArrayList;
27import java.util.concurrent.Callable;
28import java.util.concurrent.atomic.AtomicInteger;
29import java.util.concurrent.Callable;
30import java.util.concurrent.Semaphore;
31import java.util.concurrent.TimeUnit;
32import java.util.List;
33 
34/**
35 * AwContents tests.
36 */
37public class AwContentsTest extends AwTestBase {
38    public static class OnDownloadStartHelper extends CallbackHelper {
39        String mUrl;
40        String mUserAgent;
41        String mContentDisposition;
42        String mMimeType;
43        long mContentLength;
44 
45        public String getUrl() {
46            assert getCallCount() > 0;
47            return mUrl;
48        }
49 
50        public String getUserAgent() {
51            assert getCallCount() > 0;
52            return mUserAgent;
53        }
54 
55        public String getContentDisposition() {
56            assert getCallCount() > 0;
57            return mContentDisposition;
58        }
59 
60        public String getMimeType() {
61            assert getCallCount() > 0;
62            return mMimeType;
63        }
64 
65        public long getContentLength() {
66            assert getCallCount() > 0;
67            return mContentLength;
68        }
69 
70        public void notifyCalled(String url, String userAgent, String contentDisposition,
71                String mimeType, long contentLength) {
72            mUrl = url;
73            mUserAgent = userAgent;
74            mContentDisposition = contentDisposition;
75            mMimeType = mimeType;
76            mContentLength = contentLength;
77            notifyCalled();
78        }
79    }
80 
81    private static class TestAwContentsClient
82            extends org.chromium.android_webview.test.TestAwContentsClient {
83 
84        private OnDownloadStartHelper mOnDownloadStartHelper;
85 
86        public TestAwContentsClient() {
87            mOnDownloadStartHelper = new OnDownloadStartHelper();
88        }
89 
90        public OnDownloadStartHelper getOnDownloadStartHelper() {
91            return mOnDownloadStartHelper;
92        }
93 
94        @Override
95        public void onDownloadStart(String url,
96                                    String userAgent,
97                                    String contentDisposition,
98                                    String mimeType,
99                                    long contentLength) {
100            getOnDownloadStartHelper().notifyCalled(url, userAgent, contentDisposition, mimeType,
101                    contentLength);
102        }
103    }
104 
105    private TestAwContentsClient mContentsClient = new TestAwContentsClient();
106 
107    @SmallTest
108    @Feature({"AndroidWebView"})
109    @UiThreadTest
110    public void testCreateDestroy() throws Throwable {
111        // NOTE this test runs on UI thread, so we cannot call any async methods.
112        createAwTestContainerView(mContentsClient).getAwContents().destroy();
113    }
114 
115    @SmallTest
116    @Feature({"AndroidWebView"})
117    public void testCreateLoadPageDestroy() throws Throwable {
118        AwTestContainerView awTestContainerView =
119                createAwTestContainerViewOnMainSync(mContentsClient);
120        loadUrlSync(awTestContainerView.getAwContents(),
121                mContentsClient.getOnPageFinishedHelper(), CommonResources.ABOUT_HTML);
122        destroyAwContentsOnMainSync(awTestContainerView.getAwContents());
123        // It should be safe to call destroy multiple times.
124        destroyAwContentsOnMainSync(awTestContainerView.getAwContents());
125    }
126 
127    @LargeTest
128    @Feature({"AndroidWebView"})
129    public void testCreateLoadDestroyManyTimes() throws Throwable {
130        final int CREATE_AND_DESTROY_REPEAT_COUNT = 10;
131        for (int i = 0; i < CREATE_AND_DESTROY_REPEAT_COUNT; ++i) {
132            AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
133            AwContents awContents = testView.getAwContents();
134 
135            loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), "about:blank");
136            destroyAwContentsOnMainSync(awContents);
137        }
138    }
139 
140    @LargeTest
141    @Feature({"AndroidWebView"})
142    public void testCreateLoadDestroyManyAtOnce() throws Throwable {
143        final int CREATE_AND_DESTROY_REPEAT_COUNT = 10;
144        AwTestContainerView views[] = new AwTestContainerView[CREATE_AND_DESTROY_REPEAT_COUNT];
145 
146        for (int i = 0; i < views.length; ++i) {
147            views[i] = createAwTestContainerViewOnMainSync(mContentsClient);
148            loadUrlSync(views[i].getAwContents(), mContentsClient.getOnPageFinishedHelper(),
149                    "about:blank");
150        }
151 
152        for (int i = 0; i < views.length; ++i) {
153            destroyAwContentsOnMainSync(views[i].getAwContents());
154            views[i] = null;
155        }
156    }
157 
158    public void testCreateAndGcManyTimes() throws Throwable {
159        final int CONCURRENT_INSTANCES = 4;
160        final int REPETITIONS = 16;
161        // The system retains a strong ref to the last focused view (in InputMethodManager)
162        // so allow for 1 'leaked' instance.
163        final int MAX_IDLE_INSTANCES = 1;
164 
165        System.gc();
166 
167        assertTrue(pollOnUiThread(new Callable<Boolean>() {
168            @Override
169            public Boolean call() {
170                return AwContents.getNativeInstanceCount() <= MAX_IDLE_INSTANCES;
171            }
172        }));
173        for (int i = 0; i < REPETITIONS; ++i) {
174            for (int j = 0; j < CONCURRENT_INSTANCES; ++j) {
175                AwTestContainerView view = createAwTestContainerViewOnMainSync(mContentsClient);
176                loadUrlAsync(view.getAwContents(), "about:blank");
177            }
178            assertTrue(AwContents.getNativeInstanceCount() >= CONCURRENT_INSTANCES);
179            assertTrue(AwContents.getNativeInstanceCount() <= (i + 1) * CONCURRENT_INSTANCES);
180            runTestOnUiThread(new Runnable() {
181                @Override
182                public void run() {
183                    getActivity().removeAllViews();
184                }
185            });
186        }
187 
188        System.gc();
189 
190        assertTrue(pollOnUiThread(new Callable<Boolean>() {
191            @Override
192            public Boolean call() {
193                return AwContents.getNativeInstanceCount() <= MAX_IDLE_INSTANCES;
194            }
195        }));
196    }
197 
198    private int callDocumentHasImagesSync(final AwContents awContents)
199            throws Throwable, InterruptedException {
200        // Set up a container to hold the result object and a semaphore to
201        // make the test wait for the result.
202        final AtomicInteger val = new AtomicInteger();
203        final Semaphore s = new Semaphore(0);
204        final Message msg = Message.obtain(new Handler(Looper.getMainLooper()) {
205            @Override
206            public void handleMessage(Message msg) {
207                val.set(msg.arg1);
208                s.release();
209            }
210        });
211        runTestOnUiThread(new Runnable() {
212            @Override
213            public void run() {
214              awContents.documentHasImages(msg);
215            }
216        });
217        assertTrue(s.tryAcquire(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS));
218        int result = val.get();
219        return result;
220    }
221 
222    @SmallTest
223    @Feature({"AndroidWebView"})
224    public void testDocumentHasImages() throws Throwable {
225        AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
226        AwContents awContents = testView.getAwContents();
227 
228        final CallbackHelper loadHelper = mContentsClient.getOnPageFinishedHelper();
229 
230        final String mime = "text/html";
231        final String emptyDoc = "<head/><body/>";
232        final String imageDoc = "<head/><body><img/><img/></body>";
233 
234        // Make sure a document that does not have images returns 0
235        loadDataSync(awContents, loadHelper, emptyDoc, mime, false);
236        int result = callDocumentHasImagesSync(awContents);
237        assertEquals(0, result);
238 
239        // Make sure a document that does have images returns 1
240        loadDataSync(awContents, loadHelper, imageDoc, mime, false);
241        result = callDocumentHasImagesSync(awContents);
242        assertEquals(1, result);
243    }
244 
245    @SmallTest
246    @Feature({"AndroidWebView"})
247    public void testClearCacheMemoryAndDisk() throws Throwable {
248        final AwTestContainerView testContainer =
249                createAwTestContainerViewOnMainSync(mContentsClient);
250        final AwContents awContents = testContainer.getAwContents();
251 
252        TestWebServer webServer = null;
253        try {
254            webServer = new TestWebServer(false);
255            final String pagePath = "/clear_cache_test.html";
256            List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
257            // Set Cache-Control headers to cache this request. One century should be long enough.
258            headers.add(Pair.create("Cache-Control", "max-age=3153600000"));
259            headers.add(Pair.create("Last-Modified", "Wed, 3 Oct 2012 00:00:00 GMT"));
260            final String pageUrl = webServer.setResponse(
261                    pagePath, "<html><body>foo</body></html>", headers);
262 
263            // First load to populate cache.
264            clearCacheOnUiThread(awContents, true);
265            loadUrlSync(awContents,
266                        mContentsClient.getOnPageFinishedHelper(),
267                        pageUrl);
268            assertEquals(1, webServer.getRequestCount(pagePath));
269 
270            // Load about:blank so next load is not treated as reload by webkit and force
271            // revalidate with the server.
272            loadUrlSync(awContents,
273                        mContentsClient.getOnPageFinishedHelper(),
274                        "about:blank");
275 
276            // No clearCache call, so should be loaded from cache.
277            loadUrlSync(awContents,
278                        mContentsClient.getOnPageFinishedHelper(),
279                        pageUrl);
280            assertEquals(1, webServer.getRequestCount(pagePath));
281 
282            // Same as above.
283            loadUrlSync(awContents,
284                        mContentsClient.getOnPageFinishedHelper(),
285                        "about:blank");
286 
287            // Clear cache, so should hit server again.
288            clearCacheOnUiThread(awContents, true);
289            loadUrlSync(awContents,
290                        mContentsClient.getOnPageFinishedHelper(),
291                        pageUrl);
292            assertEquals(2, webServer.getRequestCount(pagePath));
293        } finally {
294            if (webServer != null) webServer.shutdown();
295        }
296    }
297 
298    @SmallTest
299    @Feature({"AndroidWebView"})
300    public void testClearCacheInQuickSuccession() throws Throwable {
301        final AwTestContainerView testContainer =
302                createAwTestContainerViewOnMainSync(new TestAwContentsClient());
303        final AwContents awContents = testContainer.getAwContents();
304 
305        runTestOnUiThread(new Runnable() {
306            @Override
307            public void run() {
308              for (int i = 0; i < 10; ++i) {
309                  awContents.clearCache(true);
310              }
311            }
312        });
313    }
314 
315    private static final long TEST_TIMEOUT = 20000L;
316    private static final int CHECK_INTERVAL = 100;
317 
318    @SmallTest
319    @Feature({"AndroidWebView"})
320    public void testGetFavicon() throws Throwable {
321        final AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
322        final AwContents awContents = testView.getAwContents();
323 
324        TestWebServer webServer = null;
325        try {
326            webServer = new TestWebServer(false);
327 
328            final String faviconUrl = webServer.setResponseBase64(
329                    "/" + CommonResources.FAVICON_FILENAME, CommonResources.FAVICON_DATA_BASE64,
330                    CommonResources.getImagePngHeaders(false));
331            final String pageUrl = webServer.setResponse("/favicon.html",
332                    CommonResources.FAVICON_STATIC_HTML, null);
333 
334            // The getFavicon will return the right icon a certain time after
335            // the page load completes which makes it slightly hard to test.
336            final Bitmap defaultFavicon = awContents.getFavicon();
337 
338            getAwSettingsOnUiThread(awContents).setImagesEnabled(true);
339            loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl);
340 
341            assertTrue(pollOnUiThread(new Callable<Boolean>() {
342                @Override
343                public Boolean call() {
344                    return awContents.getFavicon() != null &&
345                        !awContents.getFavicon().sameAs(defaultFavicon);
346                }
347            }));
348 
349            final Object originalFaviconSource = (new URL(faviconUrl)).getContent();
350            final Bitmap originalFavicon =
351                BitmapFactory.decodeStream((InputStream)originalFaviconSource);
352            assertNotNull(originalFavicon);
353 
354            assertTrue(awContents.getFavicon().sameAs(originalFavicon));
355 
356        } finally {
357            if (webServer != null) webServer.shutdown();
358        }
359    }
360 
361    @Feature({"AndroidWebView", "Downloads"})
362    @SmallTest
363    public void testDownload() throws Throwable {
364        AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
365        AwContents awContents = testView.getAwContents();
366 
367        final String data = "download data";
368        final String contentDisposition = "attachment;filename=\"download.txt\"";
369        final String mimeType = "text/plain";
370 
371        List<Pair<String, String>> downloadHeaders = new ArrayList<Pair<String, String>>();
372        downloadHeaders.add(Pair.create("Content-Disposition", contentDisposition));
373        downloadHeaders.add(Pair.create("Content-Type", mimeType));
374        downloadHeaders.add(Pair.create("Content-Length", Integer.toString(data.length())));
375 
376        TestWebServer webServer = null;
377        try {
378            webServer = new TestWebServer(false);
379            final String pageUrl = webServer.setResponse(
380                    "/download.txt", data, downloadHeaders);
381            final OnDownloadStartHelper downloadStartHelper =
382                mContentsClient.getOnDownloadStartHelper();
383            final int callCount = downloadStartHelper.getCallCount();
384            loadUrlAsync(awContents, pageUrl);
385            downloadStartHelper.waitForCallback(callCount);
386 
387            assertEquals(pageUrl, downloadStartHelper.getUrl());
388            assertEquals(contentDisposition, downloadStartHelper.getContentDisposition());
389            assertEquals(mimeType, downloadStartHelper.getMimeType());
390            assertEquals(data.length(), downloadStartHelper.getContentLength());
391        } finally {
392            if (webServer != null) webServer.shutdown();
393        }
394    }
395}

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