1e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard/*
2e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * Copyright (C) 2010 The Android Open Source Project
3e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard *
4e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * Licensed under the Apache License, Version 2.0 (the "License");
5e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * you may not use this file except in compliance with the License.
6e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * You may obtain a copy of the License at
7e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard *
8e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard *      http://www.apache.org/licenses/LICENSE-2.0
9e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard *
10e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * Unless required by applicable law or agreed to in writing, software
11e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * distributed under the License is distributed on an "AS IS" BASIS,
12e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * See the License for the specific language governing permissions and
14e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * limitations under the License.
15e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard */
16e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
17e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howardpackage com.android.providers.downloads;
18e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
1958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static java.net.HttpURLConnection.HTTP_OK;
2058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
21a1448628237471a7a2aeb67b560b1502c2bd5ba8Steve Howardimport android.app.DownloadManager;
22e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howardimport android.test.suitebuilder.annotation.LargeTest;
235ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkeyimport android.util.Pair;
245ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
255ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkeyimport com.google.android.collect.Lists;
265ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkeyimport com.google.android.collect.Sets;
275ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkeyimport com.google.mockwebserver.MockResponse;
285ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkeyimport com.google.mockwebserver.SocketPolicy;
295ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
30dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport java.util.HashSet;
315ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkeyimport java.util.List;
325ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkeyimport java.util.Set;
33e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
34e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard/**
35e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard * Download manager tests that require multithreading.
36e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard */
37e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard@LargeTest
38e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howardpublic class ThreadingTest extends AbstractPublicApiTest {
39e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    public ThreadingTest() {
408ac10e0e0667a4fe35191deebb5fa9786bf4226cJeff Sharkey        super(new FakeSystemFacade());
41e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    }
42e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
43e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    @Override
44e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    protected void tearDown() throws Exception {
45e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        Thread.sleep(50); // give threads a chance to finish
46e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        super.tearDown();
47e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    }
48e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
49e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    /**
50e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard     * Test for race conditions when the service is flooded with startService() calls while running
51e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard     * a download.
52e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard     */
53e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    public void testFloodServiceWithStarts() throws Exception {
54ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
55e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        Download download = enqueueRequest(getRequest());
56e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        while (download.getStatus() != DownloadManager.STATUS_SUCCESSFUL) {
57e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard            startService(null);
58e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard            Thread.sleep(10);
59e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        }
60e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    }
615ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
625ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey    public void testFilenameRace() throws Exception {
635ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        final List<Pair<Download, String>> downloads = Lists.newArrayList();
64dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final HashSet<String> expectedBodies = Sets.newHashSet();
655ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
665ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        // Request dozen files at once with same name
67dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        for (int i = 0; i < 32; i++) {
685ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            final String body = "DOWNLOAD " + i + " CONTENTS";
695ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            enqueueResponse(new MockResponse().setResponseCode(HTTP_OK).setBody(body)
705ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey                    .setHeader("Content-type", "text/plain")
715ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey                    .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END));
725ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
735ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            final Download d = enqueueRequest(getRequest());
745ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            downloads.add(Pair.create(d, body));
75dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            expectedBodies.add(body);
765ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        }
775ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
785ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        // Kick off downloads in parallel
795ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        final long startMillis = mSystemFacade.currentTimeMillis();
805ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        startService(null);
815ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
825ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        for (Pair<Download,String> d : downloads) {
835ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            d.first.waitForStatus(DownloadManager.STATUS_SUCCESSFUL, startMillis);
845ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        }
855ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
865ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        // Ensure that contents are clean and filenames unique
875ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        final Set<String> seenFiles = Sets.newHashSet();
88dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final HashSet<String> actualBodies = Sets.newHashSet();
895ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
905ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        for (Pair<Download, String> d : downloads) {
915ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            final String file = d.first.getStringField(DownloadManager.COLUMN_LOCAL_FILENAME);
925ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            if (!seenFiles.add(file)) {
935ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey                fail("Another download already claimed " + file);
945ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            }
955ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey
965ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            final String expected = d.second;
975ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey            final String actual = d.first.getContents();
98dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
99dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            actualBodies.add(actual);
1005ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey        }
101dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
102dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        assertEquals(expectedBodies, actualBodies);
1035ba69740a47857fcebd36866e07963ba798269d5Jeff Sharkey    }
104e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard}
105