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