184769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay/*
284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * Copyright (C) 2016 The Android Open Source Project
384769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay *
484769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * Licensed under the Apache License, Version 2.0 (the "License");
584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * you may not use this file except in compliance with the License.
684769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * You may obtain a copy of the License at
784769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay *
884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay *      http://www.apache.org/licenses/LICENSE-2.0
984769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay *
1084769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * Unless required by applicable law or agreed to in writing, software
1184769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * distributed under the License is distributed on an "AS IS" BASIS,
1284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1384769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * See the License for the specific language governing permissions and
1484769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay * limitations under the License.
1584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay */
1684769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
179666ce691a4d45344460f17cec3577dbe075235aGarfield, Tanpackage com.android.documentsui.clipping;
1884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
199666ce691a4d45344460f17cec3577dbe075235aGarfield, Tanimport static com.android.documentsui.clipping.ClipStorage.NUM_OF_SLOTS;
2084769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport static org.junit.Assert.assertEquals;
2184769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport static org.junit.Assert.assertFalse;
2284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport static org.junit.Assert.assertTrue;
2384769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
24b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tanimport android.content.SharedPreferences;
2584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport android.net.Uri;
26edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tanimport android.os.AsyncTask;
27b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tanimport android.support.test.InstrumentationRegistry;
2884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport android.support.test.filters.SmallTest;
2984769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport android.support.test.runner.AndroidJUnit4;
3084769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
31edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tanimport com.android.documentsui.testing.TestScheduledExecutorService;
3284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
33edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tanimport org.junit.AfterClass;
3484769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport org.junit.Before;
3584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport org.junit.Rule;
3684769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport org.junit.Test;
3784769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport org.junit.rules.TemporaryFolder;
3884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKayimport org.junit.runner.RunWith;
3984769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
40edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tanimport java.io.File;
41edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tanimport java.util.ArrayList;
42b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tanimport java.util.Iterator;
43edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tanimport java.util.List;
44edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan
4584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay@RunWith(AndroidJUnit4.class)
4684769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay@SmallTest
4784769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKaypublic class ClipStorageTest {
48b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan    private static final String PREF_NAME = "pref";
4984769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    private static final List<Uri> TEST_URIS = createList(
5084769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay            "content://ham/fancy",
5184769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay            "content://poodle/monkey/giraffe");
5284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
5384769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    @Rule
5484769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    public TemporaryFolder folder = new TemporaryFolder();
5584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
56b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan    private SharedPreferences mPref;
57edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan    private TestScheduledExecutorService mExecutor;
5884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    private ClipStorage mStorage;
5984769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
60c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay    private int mSlot;
61edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan
6284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    @Before
6384769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    public void setUp() {
64b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        mPref = InstrumentationRegistry.getContext().getSharedPreferences(PREF_NAME, 0);
6584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        File clipDir = ClipStorage.prepareStorage(folder.getRoot());
66b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        mStorage = new ClipStorage(clipDir, mPref);
67edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan
68edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan        mExecutor = new TestScheduledExecutorService();
69edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan        AsyncTask.setDefaultExecutor(mExecutor);
70edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan
71c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        mSlot = mStorage.claimStorageSlot();
72edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan    }
73edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan
74edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan    @AfterClass
75edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan    public static void tearDownOnce() {
76edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan        AsyncTask.setDefaultExecutor(AsyncTask.SERIAL_EXECUTOR);
7784769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    }
7884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
7984769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    @Test
80edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan    public void testWrite() throws Exception {
81c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        writeAll(mSlot, TEST_URIS);
8284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    }
8384769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
8484769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    @Test
8584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    public void testRead() throws Exception {
86c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        writeAll(mSlot, TEST_URIS);
87edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan        List<Uri> uris = new ArrayList<>();
88b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan
89c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        File copy = mStorage.getFile(mSlot);
909666ce691a4d45344460f17cec3577dbe075235aGarfield, Tan        try(ClipStorageReader provider = mStorage.createReader(copy)) {
91edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan            for (Uri uri : provider) {
92edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan                uris.add(uri);
93edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan            }
94edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan        }
9584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        assertEquals(TEST_URIS, uris);
9684769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    }
9784769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
9884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    @Test
999666ce691a4d45344460f17cec3577dbe075235aGarfield, Tan    public void testClaimStorageSlot_NoAvailableSlot() throws Exception {
100c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        int firstSlot = mStorage.claimStorageSlot();
101c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        writeAll(firstSlot, TEST_URIS);
102c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        mStorage.getFile(firstSlot);
103b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        for (int i = 0; i < NUM_OF_SLOTS - 1; ++i) {
104c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay            int slot = mStorage.claimStorageSlot();
105c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay            writeAll(slot, TEST_URIS);
106c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay            mStorage.getFile(slot);
107b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        }
108b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan
109c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        assertEquals(firstSlot, mStorage.claimStorageSlot());
110b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan    }
111b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan
112b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan    @Test
113b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan    public void testReadConcurrently() throws Exception {
114c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        writeAll(mSlot, TEST_URIS);
115b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        List<Uri> uris = new ArrayList<>();
116b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        List<Uri> uris2 = new ArrayList<>();
117b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan
118c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        File copy = mStorage.getFile(mSlot);
119c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        File copy2 = mStorage.getFile(mSlot);
1209666ce691a4d45344460f17cec3577dbe075235aGarfield, Tan        try(ClipStorageReader reader = mStorage.createReader(copy)) {
1219666ce691a4d45344460f17cec3577dbe075235aGarfield, Tan            try(ClipStorageReader reader2 = mStorage.createReader(copy2)){
122b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan                Iterator<Uri> iter = reader.iterator();
123b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan                Iterator<Uri> iter2 = reader2.iterator();
124b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan
125b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan                while (iter.hasNext() && iter2.hasNext()) {
126b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan                    uris.add(iter.next());
127b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan                    uris2.add(iter2.next());
128b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan                }
129b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan
130b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan                assertFalse(iter.hasNext());
131b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan                assertFalse(iter2.hasNext());
132b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan            }
133b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        }
134b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        assertEquals(TEST_URIS, uris);
135b7e5f6b55f5075e4752bd94586211fae9af2bae0Garfield, Tan        assertEquals(TEST_URIS, uris2);
13684769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    }
13784769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
13884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    @Test
13984769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    public void testPrepareStorage_CreatesDir() throws Exception {
14084769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        File clipDir = ClipStorage.prepareStorage(folder.getRoot());
14184769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        assertTrue(clipDir.exists());
14284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        assertTrue(clipDir.isDirectory());
14384769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        assertFalse(clipDir.equals(folder.getRoot()));
14484769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    }
14584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
146c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay    private void writeAll(int slot, List<Uri> uris) {
147c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay        mStorage.persistUris(uris, slot);
148edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan        mExecutor.runAll();
14984769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    }
15084769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay
15184769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    private static List<Uri> createList(String... values) {
15284769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        List<Uri> uris = new ArrayList<>(values.length);
15384769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        for (int i = 0; i < values.length; i++) {
15484769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay            uris.add(i, Uri.parse(values[i]));
15584769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        }
15684769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay        return uris;
15784769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay    }
15884769b8205cf4a100c9d4f65c41cf72ba7a3b40fSteve McKay}
159