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