summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ben Reich <benreich@google.com> 2025-02-04 16:27:53 +1100
committer Ben Reich <benreich@google.com> 2025-02-04 16:51:09 +1100
commitb4a53462e1feb20a73319c1f9b14e4ae02778000 (patch)
tree7b95349e4a6dace90758b4feaf96603bca5e46fe
parent6a9ccd120b7cc4f0d9e5122daa4b3c9656bd6adc (diff)
Support test flag annotation filtering in SortDocumentUiTest
Filtering tests based on flags is a feature that is only available when running tests cases in Junit 4. Unfortunately all the functional tests are written in Junit 3. To update to Junit 4 it requires rewriting some of the base classes, specifically ActivityTest. The current ActivityTest uses the deprecated ActivityInstrumentationTestCase2 which was deprecated in favour of ActivityTestRule. Unforunately this has also since been deprecated in favour of ActivityScenario. There is quite a bit of churn in the way tests are setup, so to avoid a large sweeping CL, this introduces a minimum class required to make the SortDocumentUiTest to work. Follow up tests will be introduced to migrate the existing functional tests to Junit 4 to allow for individual tests to be filtered. Once all tests have been migrated, the file will be renamed back to ActivityTest and the old (deprecated) version will be removed. Bug: 393339189, 377771803 Test: atest SortDocumentUiTest#testSortByArrowIcon Flag: EXEMPT test change Change-Id: I408d3d7f3f644a9b9d1ce760160aef119d227c3e
-rw-r--r--tests/Android.bp3
-rw-r--r--tests/functional/com/android/documentsui/ActivityTestJunit4.kt211
-rw-r--r--tests/functional/com/android/documentsui/SortDocumentUiTest.java39
3 files changed, 245 insertions, 8 deletions
diff --git a/tests/Android.bp b/tests/Android.bp
index 2b2daa45d..f67d344dd 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -25,9 +25,11 @@ java_defaults {
],
static_libs: [
+ "androidx.test.core",
"androidx.test.espresso.core",
"androidx.test.ext.truth",
"androidx.test.rules",
+ "androidx.test.ext.junit",
"androidx.test.uiautomator_uiautomator",
"docsui-flags-aconfig-java-lib",
"flag-junit",
@@ -93,6 +95,7 @@ android_library {
srcs: [
"common/**/*.java",
"functional/**/*.java",
+ "functional/**/*.kt",
"unit/**/*.java",
],
diff --git a/tests/functional/com/android/documentsui/ActivityTestJunit4.kt b/tests/functional/com/android/documentsui/ActivityTestJunit4.kt
new file mode 100644
index 000000000..daab0cdb4
--- /dev/null
+++ b/tests/functional/com/android/documentsui/ActivityTestJunit4.kt
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.documentsui
+
+import android.app.Activity
+import android.app.UiAutomation
+import android.content.ContentResolver
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.os.RemoteException
+import android.provider.DocumentsContract
+import android.view.KeyEvent
+import android.view.MotionEvent
+import androidx.test.core.app.ActivityScenario
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.Configurator
+import androidx.test.uiautomator.UiDevice
+import com.android.documentsui.base.Features
+import com.android.documentsui.base.Features.RuntimeFeatures
+import com.android.documentsui.base.RootInfo
+import com.android.documentsui.base.UserId
+import com.android.documentsui.bots.Bots
+import com.android.documentsui.files.FilesActivity
+import java.io.IOException
+import java.util.Objects
+
+/**
+ * Provides basic test environment for UI tests:
+ * - Launches activity
+ * - Creates and gives access to test root directories and test files
+ * - Cleans up the test environment
+ */
+abstract class ActivityTestJunit4<T : Activity?> {
+ @JvmField
+ var bots: Bots? = null
+ var device: UiDevice? = null
+ var context: Context? = null
+ var userId: UserId? = null
+ var automation: UiAutomation? = null
+
+ var features: Features? = null
+
+ /**
+ * Returns the root that will be opened within the activity.
+ * By default tests are started with one of the test roots.
+ * Override the method if you want to open different root on start.
+ * @return Root that will be opened. Return null if you want to open activity's default root.
+ */
+ protected var initialRoot: RootInfo? = null
+ var rootDir1: RootInfo? = null
+ protected var mResolver: ContentResolver? = null
+
+ @JvmField
+ protected var mDocsHelper: DocumentsProviderHelper? = null
+ protected var mActivityScenario: ActivityScenario<T?>? = null
+ private var initialScreenOffTimeoutValue: String? = null
+ private var initialSleepTimeoutValue: String? = null
+
+ protected val testingProviderAuthority: String
+ /**
+ * Returns the authority of the testing provider begin used.
+ * By default it's StubProvider's authority.
+ * @return Authority of the provider.
+ */
+ get() = StubProvider.DEFAULT_AUTHORITY
+
+ /**
+ * Resolves testing roots.
+ */
+ @Throws(RemoteException::class)
+ protected fun setupTestingRoots() {
+ this.initialRoot = mDocsHelper!!.getRoot(StubProvider.ROOT_0_ID)
+ rootDir1 = mDocsHelper!!.getRoot(StubProvider.ROOT_1_ID)
+ }
+
+ @Throws(Exception::class)
+ open fun setUp() {
+ device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ // NOTE: Must be the "target" context, else security checks in content provider will fail.
+ context = InstrumentationRegistry.getInstrumentation().getTargetContext()
+ userId = UserId.DEFAULT_USER
+ automation = InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ features = RuntimeFeatures(context!!.getResources(), null)
+
+ bots = Bots(device, automation, context, TIMEOUT)
+
+ Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE)
+
+ mResolver = context!!.getContentResolver()
+ mDocsHelper = DocumentsProviderHelper(
+ userId, this.testingProviderAuthority, context,
+ this.testingProviderAuthority
+ )
+
+ device!!.setOrientationNatural()
+ device!!.pressKeyCode(KeyEvent.KEYCODE_WAKEUP)
+
+ disableScreenOffAndSleepTimeouts()
+
+ setupTestingRoots()
+
+ launchActivity()
+ resetStorage()
+
+ // Since at the launch of activity, ROOT_0 and ROOT_1 have no files, drawer will
+ // automatically open for phone devices. Espresso register click() as (x, y) MotionEvents,
+ // so if a drawer is on top of a file we want to select, it will actually click the drawer.
+ // Thus to start a clean state, we always try to close first.
+ bots!!.roots!!.closeDrawer()
+
+ // Configure the provider back to default.
+ mDocsHelper!!.configure(null, Bundle.EMPTY)
+ }
+
+ @Throws(Exception::class)
+ open fun tearDown() {
+ device!!.unfreezeRotation()
+ mDocsHelper!!.cleanUp()
+ restoreScreenOffAndSleepTimeouts()
+ mActivityScenario!!.close()
+ }
+
+ protected fun launchActivity() {
+ val intent = Intent(context, FilesActivity::class.java)
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
+ if (this.initialRoot != null) {
+ intent.setAction(Intent.ACTION_VIEW)
+ intent.setDataAndType(
+ this.initialRoot!!.uri,
+ DocumentsContract.Root.MIME_TYPE_ITEM
+ )
+ }
+ mActivityScenario = ActivityScenario.launch(intent)
+ }
+
+ @Throws(RemoteException::class)
+ protected fun resetStorage() {
+ mDocsHelper!!.clear(null, null)
+ device!!.waitForIdle()
+ }
+
+ @Throws(RemoteException::class)
+ protected fun initTestFiles() {
+ mDocsHelper!!.createFolder(this.initialRoot, dirName1)
+ mDocsHelper!!.createDocument(this.initialRoot, "text/plain", fileName1)
+ mDocsHelper!!.createDocument(this.initialRoot, "image/png", fileName2)
+ mDocsHelper!!.createDocumentWithFlags(
+ initialRoot!!.documentId,
+ "text/plain",
+ fileNameNoRename,
+ DocumentsContract.Document.FLAG_SUPPORTS_WRITE
+ )
+
+ mDocsHelper!!.createDocument(rootDir1, "text/plain", fileName3)
+ mDocsHelper!!.createDocument(rootDir1, "text/plain", fileName4)
+ }
+
+ @Throws(IOException::class)
+ private fun disableScreenOffAndSleepTimeouts() {
+ initialScreenOffTimeoutValue = device!!.executeShellCommand(
+ "settings get system screen_off_timeout"
+ )
+ initialSleepTimeoutValue = device!!.executeShellCommand(
+ "settings get secure sleep_timeout"
+ )
+ device!!.executeShellCommand("settings put system screen_off_timeout -1")
+ device!!.executeShellCommand("settings put secure sleep_timeout -1")
+ }
+
+ @Throws(IOException::class)
+ private fun restoreScreenOffAndSleepTimeouts() {
+ Objects.requireNonNull<String?>(initialScreenOffTimeoutValue)
+ Objects.requireNonNull<String?>(initialSleepTimeoutValue)
+ try {
+ device!!.executeShellCommand(
+ "settings put system screen_off_timeout $initialScreenOffTimeoutValue"
+ )
+ device!!.executeShellCommand(
+ "settings put secure sleep_timeout $initialSleepTimeoutValue"
+ )
+ } finally {
+ initialScreenOffTimeoutValue = null
+ initialSleepTimeoutValue = null
+ }
+ }
+
+ companion object {
+ // Testing files. For custom ones, override initTestFiles().
+ const val dirName1 = "Dir1"
+ const val fileName1 = "file1.log"
+ const val fileName2 = "file12.png"
+ const val fileName3 = "anotherFile0.log"
+ const val fileName4 = "poodles.text"
+ const val fileNameNoRename = "NO_RENAMEfile.txt"
+ const val TIMEOUT = 5000
+ }
+}
diff --git a/tests/functional/com/android/documentsui/SortDocumentUiTest.java b/tests/functional/com/android/documentsui/SortDocumentUiTest.java
index a6907d680..53bc372e0 100644
--- a/tests/functional/com/android/documentsui/SortDocumentUiTest.java
+++ b/tests/functional/com/android/documentsui/SortDocumentUiTest.java
@@ -19,13 +19,20 @@ package com.android.documentsui;
import android.net.Uri;
import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
import com.android.documentsui.files.FilesActivity;
import com.android.documentsui.sorting.SortDimension;
import com.android.documentsui.sorting.SortModel;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
@LargeTest
-public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
+@RunWith(AndroidJUnit4.class)
+public class SortDocumentUiTest extends ActivityTestJunit4<FilesActivity> {
private static final String DIR_1 = "folder_1";
private static final String DIR_2 = "dir_2";
@@ -52,10 +59,6 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
private static final String[] FILES_IN_TYPE_ASC = {FILE_2, FILE_3, FILE_1};
private static final String[] FILES_IN_TYPE_DESC = reverse(FILES_IN_TYPE_ASC);
- public SortDocumentUiTest() {
- super(FilesActivity.class);
- }
-
private static String[] reverse(String[] array) {
String[] ret = new String[array.length];
@@ -66,12 +69,17 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
return ret;
}
- @Override
+ @Before
public void setUp() throws Exception {
super.setUp();
bots.roots.closeDrawer();
}
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
private void initFiles() throws Exception {
initFiles(0);
}
@@ -84,24 +92,26 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
*/
private void initFiles(long sleep) throws Exception {
for (int i = 0; i < FILES.length; ++i) {
- Uri uri = mDocsHelper.createDocument(rootDir0, MIMES[i], FILES[i]);
+ Uri uri = mDocsHelper.createDocument(getInitialRoot(), MIMES[i], FILES[i]);
mDocsHelper.writeDocument(uri, FILES[i].getBytes());
Thread.sleep(sleep);
}
for (String dir : DIRS) {
- mDocsHelper.createFolder(rootDir0, dir);
+ mDocsHelper.createFolder(getInitialRoot(), dir);
Thread.sleep(sleep);
}
}
+ @Test
public void testDefaultSortByNameAscending() throws Exception {
initFiles();
bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_NAME_ASC);
}
+ @Test
public void testSortByName_Descending_listMode() throws Exception {
initFiles();
@@ -112,6 +122,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_DESC, FILES_IN_NAME_DESC);
}
+ @Test
public void testSortBySize_Ascending_listMode() throws Exception {
initFiles();
@@ -121,6 +132,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_SIZE_ASC);
}
+ @Test
public void testSortBySize_Descending_listMode() throws Exception {
initFiles();
@@ -130,6 +142,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_SIZE_DESC);
}
+ @Test
public void testSortByModified_Ascending_listMode() throws Exception {
initFiles(1000);
@@ -139,6 +152,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS, FILES);
}
+ @Test
public void testSortByModified_Descending_listMode() throws Exception {
initFiles(1000);
@@ -148,6 +162,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_MODIFIED_DESC, FILES_IN_MODIFIED_DESC);
}
+ @Test
public void testSortByType_Ascending_listMode() throws Exception {
initFiles();
@@ -158,6 +173,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_ASC);
}
+ @Test
public void testSortByType_Descending_listMode() throws Exception {
initFiles();
@@ -168,6 +184,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_DESC);
}
+ @Test
public void testSortByName_Descending_gridMode() throws Exception {
initFiles();
@@ -178,6 +195,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_DESC, FILES_IN_NAME_DESC);
}
+ @Test
public void testSortBySize_Ascending_gridMode() throws Exception {
initFiles();
@@ -187,6 +205,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_SIZE_ASC);
}
+ @Test
public void testSortBySize_Descending_gridMode() throws Exception {
initFiles();
@@ -196,6 +215,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_SIZE_DESC);
}
+ @Test
public void testSortByModified_Ascending_gridMode() throws Exception {
initFiles(1000);
@@ -205,6 +225,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS, FILES);
}
+ @Test
public void testSortByModified_Descending_gridMode() throws Exception {
initFiles(1000);
@@ -214,6 +235,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_MODIFIED_DESC, FILES_IN_MODIFIED_DESC);
}
+ @Test
public void testSortByType_Ascending_gridMode() throws Exception {
initFiles();
@@ -224,6 +246,7 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> {
bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_ASC);
}
+ @Test
public void testSortByType_Descending_gridMode() throws Exception {
initFiles();