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.EXTRA_SIZE;
20 import static com.android.documentsui.StubProvider.ROOT_0_ID;
21 import static com.android.documentsui.StubProvider.ROOT_1_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.files.FilesActivity;
35 import com.android.documentsui.filters.HugeLongTest;
36 import com.android.documentsui.services.TestNotificationService;
37 
38 import java.util.concurrent.CountDownLatch;
39 import java.util.concurrent.TimeUnit;
40 
41 /**
42 * This class tests the below points.
43 * - Cancel copying or moving file before starting it.
44 * - Cancel during copying or moving file.
45 */
46 @LargeTest
47 public class CancelFromNotificationUiTest extends ActivityTest<FilesActivity> {
48     private static final String TAG = "CancelFromNotificationUiTest";
49 
50     private static final String TARGET_FILE = "dummy.data";
51 
52     private static final int BUFFER_SIZE = 10 * 1024 * 1024;
53 
54     private static final int WAIT_TIME_SECONDS = 120;
55 
56     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
57         @Override
58         public void onReceive(Context context, Intent intent) {
59             String action = intent.getAction();
60             if (TestNotificationService.ACTION_OPERATION_RESULT.equals(action)) {
61                 mOperationExecuted = intent.getBooleanExtra(
62                         TestNotificationService.EXTRA_RESULT, false);
63                 if (!mOperationExecuted) {
64                     mErrorReason = intent.getStringExtra(
65                             TestNotificationService.EXTRA_ERROR_REASON);
66                 }
67                 mCountDownLatch.countDown();
68             }
69         }
70     };
71 
72     private CountDownLatch mCountDownLatch;
73 
74     private boolean mOperationExecuted;
75 
76     private String mErrorReason;
77 
CancelFromNotificationUiTest()78     public CancelFromNotificationUiTest() {
79         super(FilesActivity.class);
80     }
81 
82     @Override
setUp()83     public void setUp() throws Exception {
84         super.setUp();
85 
86         // super.setUp() method will change the storage size to 100MB.
87         // So, reset the storage size again to 500MB.
88         Bundle bundle = new Bundle();
89         bundle.putLong(EXTRA_SIZE, 500L);
90         // Set a flag to prevent many refreshes.
91         bundle.putBoolean(StubProvider.EXTRA_ENABLE_ROOT_NOTIFICATION, false);
92         mDocsHelper.configure(null, bundle);
93 
94         try {
95             bots.notifications.setNotificationAccess(getActivity(), true);
96         } catch (Exception e) {
97             Log.d(TAG, "Cannot set notification access. ", e);
98         }
99 
100         initTestFiles();
101 
102         IntentFilter filter = new IntentFilter();
103         filter.addAction(TestNotificationService.ACTION_OPERATION_RESULT);
104         context.registerReceiver(mReceiver, filter);
105         context.sendBroadcast(new Intent(
106                 TestNotificationService.ACTION_CHANGE_CANCEL_MODE));
107 
108         mOperationExecuted = false;
109         mErrorReason = "No response from Notification";
110         mCountDownLatch = new CountDownLatch(1);
111     }
112 
113     @Override
tearDown()114     public void tearDown() throws Exception {
115         mCountDownLatch.countDown();
116         mCountDownLatch = null;
117 
118         context.unregisterReceiver(mReceiver);
119         try {
120             bots.notifications.setNotificationAccess(getActivity(), false);
121         } catch (Exception e) {
122             Log.d(TAG, "Cannot set notification access. ", e);
123         }
124         super.tearDown();
125     }
126 
127     @Override
initTestFiles()128     public void initTestFiles() throws RemoteException {
129         try {
130             createDummyFile();
131         } catch (Exception e) {
132             fail("Initialization failed. " + e.toString());
133         }
134     }
135 
createDummyFile()136     private void createDummyFile() throws Exception {
137         Uri uri = mDocsHelper.createDocument(rootDir0, "*/*", TARGET_FILE);
138         byte[] dummyByte = new byte[BUFFER_SIZE];
139         mDocsHelper.writeDocument(uri, dummyByte);
140         for (int i = 0; i < 49; i++) {
141             dummyByte = null;
142             dummyByte = new byte[BUFFER_SIZE];
143             mDocsHelper.writeAppendDocument(uri, dummyByte, dummyByte.length);
144         }
145     }
146 
147     @HugeLongTest
testCopyDocument_Cancel()148     public void testCopyDocument_Cancel() throws Exception {
149         bots.roots.openRoot(ROOT_0_ID);
150 
151         bots.directory.findDocument(TARGET_FILE);
152         device.waitForIdle();
153 
154         bots.directory.selectDocument(TARGET_FILE, 1);
155         device.waitForIdle();
156 
157         bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_copy));
158         device.waitForIdle();
159 
160         bots.main.clickDialogCancelButton();
161         device.waitForIdle();
162 
163         bots.directory.waitForDocument(TARGET_FILE);
164     }
165 
166     @HugeLongTest
testCopyDocument_CancelFromNotification()167     public void testCopyDocument_CancelFromNotification() throws Exception {
168         bots.roots.openRoot(ROOT_0_ID);
169         bots.directory.findDocument(TARGET_FILE);
170         device.waitForIdle();
171 
172         bots.directory.selectDocument(TARGET_FILE, 1);
173         device.waitForIdle();
174 
175         bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_copy));
176         device.waitForIdle();
177 
178         bots.roots.openRoot(ROOT_1_ID);
179         bots.main.clickDialogOkButton();
180         device.waitForIdle();
181 
182         try {
183             mCountDownLatch.await(WAIT_TIME_SECONDS, TimeUnit.SECONDS);
184         } catch (Exception e) {
185             fail("Cannot wait because of error." + e.toString());
186         }
187 
188         assertTrue(mErrorReason, mOperationExecuted);
189 
190         bots.roots.openRoot(ROOT_1_ID);
191         device.waitForIdle();
192         assertFalse(bots.directory.hasDocuments(TARGET_FILE));
193 
194         bots.roots.openRoot(ROOT_0_ID);
195         device.waitForIdle();
196         assertTrue(bots.directory.hasDocuments(TARGET_FILE));
197     }
198 
199     @HugeLongTest
testMoveDocument_Cancel()200     public void testMoveDocument_Cancel() throws Exception {
201         bots.roots.openRoot(ROOT_0_ID);
202 
203         bots.directory.findDocument(TARGET_FILE);
204         device.waitForIdle();
205 
206         bots.directory.selectDocument(TARGET_FILE, 1);
207         device.waitForIdle();
208 
209         bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_move));
210         device.waitForIdle();
211 
212         bots.main.clickDialogCancelButton();
213         device.waitForIdle();
214 
215         bots.directory.waitForDocument(TARGET_FILE);
216     }
217 
218     @HugeLongTest
219     // (TODO: b/156756197) : Deflake tests
220     // Notice because this class inherits JUnit3 TestCase, the right way to suppress a test
221     // is by removing "test" from prefix, instead of adding @Ignore.
ignored_testMoveDocument_CancelFromNotification()222     public void ignored_testMoveDocument_CancelFromNotification() throws Exception {
223         bots.roots.openRoot(ROOT_0_ID);
224         bots.directory.findDocument(TARGET_FILE);
225         device.waitForIdle();
226 
227         bots.directory.selectDocument(TARGET_FILE, 1);
228         device.waitForIdle();
229 
230         bots.main.clickToolbarOverflowItem(context.getResources().getString(R.string.menu_move));
231         device.waitForIdle();
232 
233         bots.roots.openRoot(ROOT_1_ID);
234         bots.main.clickDialogOkButton();
235         device.waitForIdle();
236 
237         try {
238             mCountDownLatch.await(WAIT_TIME_SECONDS, TimeUnit.SECONDS);
239         } catch (Exception e) {
240             fail("Cannot wait because of error." + e.toString());
241         }
242 
243         assertTrue(mErrorReason, mOperationExecuted);
244 
245         bots.roots.openRoot(ROOT_1_ID);
246         device.waitForIdle();
247         assertFalse(bots.directory.hasDocuments(TARGET_FILE));
248 
249         bots.roots.openRoot(ROOT_0_ID);
250         device.waitForIdle();
251         assertTrue(bots.directory.hasDocuments(TARGET_FILE));
252     }
253 }
254