1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.documentsui;
18 
19 import static android.content.Context.RECEIVER_EXPORTED;
20 
21 import static com.android.documentsui.StubProvider.ROOT_0_ID;
22 
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.net.Uri;
28 import android.os.Bundle;
29 import android.os.RemoteException;
30 import android.util.Log;
31 
32 import androidx.test.filters.LargeTest;
33 
34 import com.android.documentsui.base.DocumentInfo;
35 import com.android.documentsui.files.FilesActivity;
36 import com.android.documentsui.filters.HugeLongTest;
37 import com.android.documentsui.services.TestNotificationService;
38 
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.concurrent.ArrayBlockingQueue;
42 import java.util.concurrent.CountDownLatch;
43 import java.util.concurrent.ThreadPoolExecutor;
44 import java.util.concurrent.TimeUnit;
45 
46 /**
47 * This class test the below points
48 * - Delete large number of files
49 */
50 @LargeTest
51 public class FileDeleteUiTest extends ActivityTest<FilesActivity> {
52     private static final String TAG = "FileDeleteUiTest";
53 
54     private static final int STUB_FILE_COUNT = 1000;
55 
56     private static final int WAIT_TIME_SECONDS = 60;
57 
58     private final List<String> mCopyFileList = new ArrayList<String>();
59 
60     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
61         @Override
62         public void onReceive(Context context, Intent intent) {
63             String action = intent.getAction();
64             if (TestNotificationService.ACTION_OPERATION_RESULT.equals(action)) {
65                 mOperationExecuted = intent.getBooleanExtra(
66                         TestNotificationService.EXTRA_RESULT, false);
67                 if (!mOperationExecuted) {
68                     mErrorReason = intent.getStringExtra(
69                             TestNotificationService.EXTRA_ERROR_REASON);
70                 }
71                 if (mCountDownLatch != null) {
72                     mCountDownLatch.countDown();
73                 }
74             }
75         }
76     };
77 
78     private CountDownLatch mCountDownLatch;
79 
80     private boolean mOperationExecuted;
81 
82     private String mErrorReason;
83 
FileDeleteUiTest()84     public FileDeleteUiTest() {
85         super(FilesActivity.class);
86     }
87 
88     @Override
setUp()89     public void setUp() throws Exception {
90         super.setUp();
91 
92         // Set a flag to prevent many refreshes.
93         Bundle bundle = new Bundle();
94         bundle.putBoolean(StubProvider.EXTRA_ENABLE_ROOT_NOTIFICATION, false);
95         mDocsHelper.configure(null, bundle);
96 
97         try {
98             bots.notifications.setNotificationAccess(getActivity(), true);
99         } catch (Exception e) {
100             Log.d(TAG, "Cannot set notification access. ", e);
101         }
102 
103         initTestFiles();
104 
105         IntentFilter filter = new IntentFilter();
106         filter.addAction(TestNotificationService.ACTION_OPERATION_RESULT);
107         context.registerReceiver(mReceiver, filter, RECEIVER_EXPORTED);
108         context.sendBroadcast(new Intent(
109                 TestNotificationService.ACTION_CHANGE_EXECUTION_MODE));
110 
111         mOperationExecuted = false;
112         mErrorReason = "No response from Notification";
113         mCountDownLatch = new CountDownLatch(1);
114     }
115 
116     @Override
tearDown()117     public void tearDown() throws Exception {
118         context.unregisterReceiver(mReceiver);
119         mCountDownLatch = null;
120         try {
121             bots.notifications.setNotificationAccess(getActivity(), false);
122         } catch (Exception e) {
123             Log.d(TAG, "Cannot set notification access. ", e);
124         }
125         super.tearDown();
126     }
127 
128     @Override
initTestFiles()129     public void initTestFiles() throws RemoteException {
130         try {
131             createStubFiles();
132         } catch (Exception e) {
133             fail("Initialization failed");
134         }
135     }
136 
createStubFiles()137     private void createStubFiles() throws Exception {
138         final ThreadPoolExecutor exec = new ThreadPoolExecutor(
139                 5, 5, 1000L, TimeUnit.MILLISECONDS,
140                         new ArrayBlockingQueue<Runnable>(100, true));
141         for (int i = 0; i < STUB_FILE_COUNT; i++) {
142             final String fileName = "file" + String.format("%04d", i) + ".log";
143             if (exec.getQueue().size() >= 80) {
144                 Thread.sleep(50);
145             }
146             exec.submit(new Runnable() {
147                 @Override
148                 public void run() {
149                     Uri uri = mDocsHelper.createDocument(rootDir0, "text/plain", fileName);
150                     try {
151                         mDocsHelper.writeDocument(uri, new byte[1]);
152                     } catch (Exception e) {
153                         // ignore
154                     }
155                 }
156             });
157             mCopyFileList.add(fileName);
158         }
159         exec.shutdown();
160     }
161 
162     @HugeLongTest
testDeleteAllDocument()163     public void testDeleteAllDocument() throws Exception {
164         bots.roots.openRoot(ROOT_0_ID);
165         bots.main.clickToolbarOverflowItem(
166                 context.getResources().getString(R.string.menu_select_all));
167         device.waitForIdle();
168 
169         bots.main.clickToolbarItem(R.id.action_menu_delete);
170         bots.main.clickDialogOkButton();
171         device.waitForIdle();
172 
173         try {
174             mCountDownLatch.await(WAIT_TIME_SECONDS, TimeUnit.SECONDS);
175         } catch (Exception e) {
176             fail("Cannot wait because of error." + e.toString());
177         }
178 
179         assertTrue(mErrorReason, mOperationExecuted);
180 
181         bots.roots.openRoot(ROOT_0_ID);
182         device.waitForIdle();
183 
184         List<DocumentInfo> root1 = mDocsHelper.listChildren(rootDir0.documentId, 1000);
185         assertTrue("Delete operation was not completed", root1.size() == 0);
186     }
187 }
188