diff options
Diffstat (limited to 'tests')
15 files changed, 346 insertions, 175 deletions
diff --git a/tests/Android.bp b/tests/Android.bp index fa0cdf270b..e7f408487d 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -51,6 +51,7 @@ filegroup { "src/com/android/launcher3/util/WidgetUtils.java", "src/com/android/launcher3/util/rule/FailureWatcher.java", "src/com/android/launcher3/util/rule/LauncherActivityRule.java", + "src/com/android/launcher3/util/rule/ViewCaptureRule.kt", "src/com/android/launcher3/util/rule/SamplerRule.java", "src/com/android/launcher3/util/rule/ScreenRecordRule.java", "src/com/android/launcher3/util/rule/ShellCommandRule.java", @@ -132,4 +133,4 @@ android_library { manifest: "shared/AndroidManifest.xml", sdk_version: "current", min_sdk_version: min_launcher3_sdk_version, - }
\ No newline at end of file + } diff --git a/tests/src/com/android/launcher3/DeleteDropTargetTest.kt b/tests/src/com/android/launcher3/DeleteDropTargetTest.kt index 84c617c30d..bcfb90b4ec 100644 --- a/tests/src/com/android/launcher3/DeleteDropTargetTest.kt +++ b/tests/src/com/android/launcher3/DeleteDropTargetTest.kt @@ -8,7 +8,6 @@ import com.android.launcher3.Utilities.* import com.android.launcher3.util.ActivityContextWrapper import com.google.common.truth.Truth.assertThat import org.junit.Before -import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith @@ -26,19 +25,15 @@ class DeleteDropTargetTest { enableRunningInTestHarnessForTests() } - // Needs mText, mTempRect, getPaddingTop, getPaddingBottom - // availableHeight as a parameter - @Ignore("TODO(b/279464742)") @Test fun isTextClippedVerticallyTest() { - buttonDropTarget.mText = "My Test" + buttonDropTarget.updateText("My Test") + buttonDropTarget.setPadding(0, 0, 0, 0) + buttonDropTarget.setTextMultiLine(false) // No space for text assertThat(buttonDropTarget.isTextClippedVertically(30)).isTrue() - // Some space for text, and just enough that the text should not be clipped - assertThat(buttonDropTarget.isTextClippedVertically(50)).isFalse() - // A lot of space for text so the text should not be clipped assertThat(buttonDropTarget.isTextClippedVertically(100)).isFalse() } diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java index e3de500bde..ee05fe6a9f 100644 --- a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java +++ b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java @@ -87,15 +87,13 @@ public class ReorderAlgorithmUnitTest { // modify the device profile. dp.inv.numColumns = width; dp.inv.numRows = height; + dp.cellLayoutBorderSpacePx = new Point(0, 0); CellLayout cl = new CellLayout(getWrappedContext(c, dp)); // I put a very large number for width and height so that all the items can fit, it doesn't // need to be exact, just bigger than the sum of cell border cl.measure(View.MeasureSpec.makeMeasureSpec(10000, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(10000, View.MeasureSpec.EXACTLY)); - - cl.measure(View.MeasureSpec.makeMeasureSpec(cl.getDesiredWidth(), View.MeasureSpec.EXACTLY), - View.MeasureSpec.makeMeasureSpec(cl.getDesiredHeight(), View.MeasureSpec.EXACTLY)); return cl; } diff --git a/tests/src/com/android/launcher3/icons/IconCacheTest.java b/tests/src/com/android/launcher3/icons/IconCacheTest.java index 08d6df37ad..495d583b09 100644 --- a/tests/src/com/android/launcher3/icons/IconCacheTest.java +++ b/tests/src/com/android/launcher3/icons/IconCacheTest.java @@ -116,7 +116,7 @@ public class IconCacheTest { @Nullable ComponentName cn, @Nullable String badgeOverride) throws Exception { Builder builder = new Builder(context, "test-shortcut") .setIntent(new Intent(Intent.ACTION_VIEW)) - .setTitle("Test"); + .setShortLabel("Test"); if (cn != null) { builder.setActivity(cn); } diff --git a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java index 0a1a9ba6a9..cea95e5a50 100644 --- a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java +++ b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java @@ -39,6 +39,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.R; +import com.android.launcher3.pm.UserCache; import org.junit.Before; import org.junit.Test; @@ -222,7 +223,9 @@ public class DbDowngradeHelperTest { private class MyDatabaseHelper extends DatabaseHelper { MyDatabaseHelper() { - super(mContext, DB_FILE, false); + super(mContext, DB_FILE, + UserCache.INSTANCE.get(mContext)::getSerialNumberForUser, + () -> { }); } @Override diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt index f24f0dab76..3b480cac10 100644 --- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt +++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt @@ -15,6 +15,7 @@ */ package com.android.launcher3.model +import android.content.ContentValues import android.content.Context import android.content.Intent import android.database.Cursor @@ -23,6 +24,7 @@ import android.graphics.Point import android.os.Process import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.InvariantDeviceProfile import com.android.launcher3.LauncherPrefs import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE @@ -32,7 +34,6 @@ import com.android.launcher3.model.GridSizeMigrationUtil.DbReader import com.android.launcher3.pm.UserCache import com.android.launcher3.provider.LauncherDbUtils import com.android.launcher3.util.LauncherModelHelper -import com.android.launcher3.util.LauncherModelHelper.* import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before @@ -43,11 +44,13 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class GridSizeMigrationUtilTest { + private lateinit var modelHelper: LauncherModelHelper private lateinit var context: Context - private lateinit var db: SQLiteDatabase private lateinit var validPackages: Set<String> private lateinit var idp: InvariantDeviceProfile + private lateinit var dbHelper: DatabaseHelper + private lateinit var db: SQLiteDatabase private val testPackage1 = "com.android.launcher3.validpackage1" private val testPackage2 = "com.android.launcher3.validpackage2" private val testPackage3 = "com.android.launcher3.validpackage3" @@ -63,11 +66,16 @@ class GridSizeMigrationUtilTest { fun setUp() { modelHelper = LauncherModelHelper() context = modelHelper.sandboxContext - db = modelHelper.provider.db + dbHelper = + DatabaseHelper( + context, + null, + UserCache.INSTANCE.get(context)::getSerialNumberForUser + ) {} + db = dbHelper.writableDatabase validPackages = setOf( - TEST_PACKAGE, testPackage1, testPackage2, testPackage3, @@ -99,26 +107,26 @@ class GridSizeMigrationUtilTest { @Throws(Exception::class) fun testMigration() { // Src Hotseat icons - modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE) // Src grid icons // _ _ _ _ _ // _ _ _ _ 5 // _ _ 6 _ 7 // _ _ 8 _ 9 // _ _ _ _ _ - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 3, testPackage9, 9, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 3, testPackage9, 9, TMP_TABLE) // Dest hotseat icons - modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2) + addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2) // Dest grid icons - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage10) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage10) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 4 @@ -126,8 +134,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -138,12 +145,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items var c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -168,12 +176,13 @@ class GridSizeMigrationUtilTest { // Check workspace items c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(CELLX, CELLY, INTENT), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -209,30 +218,30 @@ class GridSizeMigrationUtilTest { fun testMigrationBackAndForth() { // Hotseat items in grid A // 1 2 _ 3 4 - modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE) // Workspace items in grid A // _ _ _ _ _ // _ _ _ _ 5 // _ _ 6 _ 7 // _ _ 8 _ _ // _ _ _ _ _ - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE) // Hotseat items in grid B // 2 _ _ _ - modelHelper.addItem(SHORTCUT, 0, HOTSEAT, 0, 0, testPackage2) + addItem(ITEM_TYPE_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2) // Workspace items in grid B // _ _ _ _ // _ _ _ 10 // _ _ _ _ // _ _ _ _ - modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 3, testPackage10) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 3, testPackage10) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 4 @@ -241,8 +250,7 @@ class GridSizeMigrationUtilTest { val readerGridB = DbReader(db, TABLE_NAME, context, validPackages) // migrate from A -> B GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, readerGridA, readerGridB, idp.numDatabaseHotseatIcons, @@ -253,12 +261,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items in grid B var c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -272,12 +281,13 @@ class GridSizeMigrationUtilTest { // Check workspace items in grid B c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, CELLX, CELLY, INTENT), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -294,12 +304,11 @@ class GridSizeMigrationUtilTest { assertThat(locMap[testPackage8]).isEqualTo(Triple(0, 3, 1)) // add item in B - modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 2, testPackage9) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 2, testPackage9) // migrate from B -> A GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, readerGridB, readerGridA, 5, @@ -309,12 +318,13 @@ class GridSizeMigrationUtilTest { ) // Check hotseat items in grid A c = - context.contentResolver.query( - TMP_CONTENT_URI, + db.query( + TMP_TABLE, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -328,12 +338,13 @@ class GridSizeMigrationUtilTest { // Check workspace items in grid A c = - context.contentResolver.query( - TMP_CONTENT_URI, + db.query( + TMP_TABLE, arrayOf(SCREEN, CELLX, CELLY, INTENT), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -354,12 +365,11 @@ class GridSizeMigrationUtilTest { assertThat(locMap[testPackage9]).isEqualTo(Triple(0, 0, 2)) // remove item from B - modelHelper.deleteItem(7, TMP_TABLE) + db.delete(TMP_TABLE, "$_ID=7", null) // migrate from A -> B GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, readerGridA, readerGridB, idp.numDatabaseHotseatIcons, @@ -370,12 +380,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items in grid B c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -389,12 +400,13 @@ class GridSizeMigrationUtilTest { // Check workspace items in grid B c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, CELLX, CELLY, INTENT), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -443,10 +455,28 @@ class GridSizeMigrationUtilTest { fun migrateToLargerHotseat() { val srcHotseatItems = intArrayOf( - modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI), - modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI), - modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI), - modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI) + addItem( + ITEM_TYPE_APPLICATION, + 0, + CONTAINER_HOTSEAT, + 0, + 0, + testPackage1, + 1, + TMP_TABLE + ), + addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE), + addItem( + ITEM_TYPE_APPLICATION, + 2, + CONTAINER_HOTSEAT, + 0, + 0, + testPackage3, + 3, + TMP_TABLE + ), + addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE) ) val numSrcDatabaseHotseatIcons = srcHotseatItems.size idp.numDatabaseHotseatIcons = 6 @@ -455,8 +485,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -467,12 +496,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -501,11 +531,11 @@ class GridSizeMigrationUtilTest { @Test fun migrateFromLargerHotseat() { - modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 2, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 5, HOTSEAT, 0, 0, testPackage5, 5, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 5, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 4 @@ -513,8 +543,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -525,12 +554,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -568,11 +598,11 @@ class GridSizeMigrationUtilTest { enableNewMigrationLogic("4,4") // Setup src grid - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage1, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage2, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 1, testPackage3, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 2, testPackage4, 8, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 2, DESKTOP, 3, 3, testPackage5, 9, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage1, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage2, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 1, testPackage3, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 2, testPackage4, 8, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 3, 3, testPackage5, 9, TMP_TABLE) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 6 @@ -581,8 +611,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -593,12 +622,13 @@ class GridSizeMigrationUtilTest { // Get workspace items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(INTENT, SCREEN), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -630,11 +660,11 @@ class GridSizeMigrationUtilTest { enableNewMigrationLogic("2,2") // Setup src grid - modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 5 @@ -642,8 +672,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -654,12 +683,13 @@ class GridSizeMigrationUtilTest { // Get workspace items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(INTENT, SCREEN), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -691,11 +721,11 @@ class GridSizeMigrationUtilTest { enableNewMigrationLogic("5,5") // Setup src grid - modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 4 @@ -703,8 +733,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -715,12 +744,13 @@ class GridSizeMigrationUtilTest { // Get workspace items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(INTENT, SCREEN), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -747,4 +777,48 @@ class GridSizeMigrationUtilTest { private fun enableNewMigrationLogic(srcGridSize: String) { LauncherPrefs.get(context).putSync(WORKSPACE_SIZE.to(srcGridSize)) } + + private fun addItem( + type: Int, + screen: Int, + container: Int, + x: Int, + y: Int, + packageName: String? + ): Int { + return addItem( + type, + screen, + container, + x, + y, + packageName, + dbHelper.generateNewItemId(), + TABLE_NAME + ) + } + + private fun addItem( + type: Int, + screen: Int, + container: Int, + x: Int, + y: Int, + packageName: String?, + id: Int, + tableName: String + ): Int { + val values = ContentValues() + values.put(_ID, id) + values.put(CONTAINER, container) + values.put(SCREEN, screen) + values.put(CELLX, x) + values.put(CELLY, y) + values.put(SPANX, 1) + values.put(SPANY, 1) + values.put(ITEM_TYPE, type) + values.put(INTENT, Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0)) + db.insert(tableName, null, values) + return id + } } diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java index d192be408c..78812c0778 100644 --- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java +++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java @@ -59,7 +59,6 @@ import androidx.test.filters.SmallTest; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.util.Executors; @@ -102,7 +101,7 @@ public class LoaderCursorTest { }); UserManagerState ums = new UserManagerState(); - mLoaderCursor = new LoaderCursor(mCursor, Favorites.CONTENT_URI, mApp, ums); + mLoaderCursor = new LoaderCursor(mCursor, mApp, ums); ums.allUsers.put(0, Process.myUserHandle()); } diff --git a/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java b/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java index 2b6f9ff193..d1befd0638 100644 --- a/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java +++ b/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java @@ -45,6 +45,7 @@ import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.R; import com.android.launcher3.model.DatabaseHelper; import com.android.launcher3.model.DbDowngradeHelper; +import com.android.launcher3.pm.UserCache; import com.android.launcher3.settings.SettingsActivity; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.IOUtils; @@ -128,7 +129,6 @@ public class LauncherDbUtilsTest { assertEquals(1, getFavoriteDataCount(db)); ShortcutInfo info = mInfoArgumentCaptor.getValue(); assertNotNull(info); - assertEquals("Hello", info.getTitle()); try (Cursor c = db.query(Favorites.TABLE_NAME, null, null, null, null, null, null)) { c.moveToNext(); assertEquals(Favorites.ITEM_TYPE_DEEP_SHORTCUT, c.getInt(c.getColumnIndex(ITEM_TYPE))); @@ -165,12 +165,11 @@ public class LauncherDbUtilsTest { private class MyDatabaseHelper extends DatabaseHelper { MyDatabaseHelper() { - super(mContext, null, false); + super(mContext, null, UserCache.INSTANCE.get(mContext)::getSerialNumberForUser, + () -> { }); } @Override protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { } - - protected void onEmptyDbCreated() { } } } diff --git a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java index 67de1f5fb1..73bb5865ee 100644 --- a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java +++ b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java @@ -45,8 +45,11 @@ import androidx.test.filters.SmallTest; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; -import com.android.launcher3.model.DatabaseHelper; +import com.android.launcher3.model.ModelDbController; +import com.android.launcher3.util.LauncherModelHelper; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -61,15 +64,29 @@ public class RestoreDbTaskTest { private final UserHandle mWorkUser = UserHandle.getUserHandleForUid(PER_USER_RANGE); + private LauncherModelHelper mModelHelper; + private Context mContext; + + @Before + public void setup() { + mModelHelper = new LauncherModelHelper(); + mContext = mModelHelper.sandboxContext; + } + + @After + public void teardown() { + mModelHelper.destroy(); + } + @Test public void testGetProfileId() throws Exception { - SQLiteDatabase db = new MyDatabaseHelper(23).getWritableDatabase(); + SQLiteDatabase db = new MyModelDbController(23).getDb(); assertEquals(23, new RestoreDbTask().getDefaultProfileId(db)); } @Test public void testMigrateProfileId() throws Exception { - SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase(); + SQLiteDatabase db = new MyModelDbController(42).getDb(); // Add some mock data for (int i = 0; i < 5; i++) { ContentValues values = new ContentValues(); @@ -89,7 +106,7 @@ public class RestoreDbTaskTest { @Test public void testChangeDefaultColumn() throws Exception { - SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase(); + SQLiteDatabase db = new MyModelDbController(42).getDb(); // Add some mock data for (int i = 0; i < 5; i++) { ContentValues values = new ContentValues(); @@ -112,28 +129,27 @@ public class RestoreDbTaskTest { @Test public void testSanitizeDB_bothProfiles() throws Exception { - Context context = getInstrumentation().getTargetContext(); UserHandle myUser = myUserHandle(); - long myProfileId = context.getSystemService(UserManager.class) + long myProfileId = mContext.getSystemService(UserManager.class) .getSerialNumberForUser(myUser); long myProfileId_old = myProfileId + 1; long workProfileId = myProfileId + 2; long workProfileId_old = myProfileId + 3; - MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId); - SQLiteDatabase db = helper.getWritableDatabase(); - BackupManager bm = spy(new BackupManager(context)); + MyModelDbController controller = new MyModelDbController(myProfileId); + SQLiteDatabase db = controller.getDb(); + BackupManager bm = spy(new BackupManager(mContext)); doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old)); doReturn(mWorkUser).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old)); - helper.users.put(workProfileId, mWorkUser); + controller.users.put(workProfileId, mWorkUser); - addIconsBulk(helper, 10, 1, myProfileId_old); - addIconsBulk(helper, 6, 2, workProfileId_old); + addIconsBulk(controller, 10, 1, myProfileId_old); + addIconsBulk(controller, 6, 2, workProfileId_old); assertEquals(10, getItemCountForProfile(db, myProfileId_old)); assertEquals(6, getItemCountForProfile(db, workProfileId_old)); RestoreDbTask task = new RestoreDbTask(); - task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm); + task.sanitizeDB(mContext, controller, controller.getDb(), bm); // All the data has been migrated to the new user ids assertEquals(0, getItemCountForProfile(db, myProfileId_old)); @@ -144,27 +160,26 @@ public class RestoreDbTaskTest { @Test public void testSanitizeDB_workItemsRemoved() throws Exception { - Context context = getInstrumentation().getTargetContext(); UserHandle myUser = myUserHandle(); - long myProfileId = context.getSystemService(UserManager.class) + long myProfileId = mContext.getSystemService(UserManager.class) .getSerialNumberForUser(myUser); long myProfileId_old = myProfileId + 1; long workProfileId_old = myProfileId + 3; - MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId); - SQLiteDatabase db = helper.getWritableDatabase(); - BackupManager bm = spy(new BackupManager(context)); + MyModelDbController controller = new MyModelDbController(myProfileId); + SQLiteDatabase db = controller.getDb(); + BackupManager bm = spy(new BackupManager(mContext)); doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old)); // Work profile is not migrated doReturn(null).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old)); - addIconsBulk(helper, 10, 1, myProfileId_old); - addIconsBulk(helper, 6, 2, workProfileId_old); + addIconsBulk(controller, 10, 1, myProfileId_old); + addIconsBulk(controller, 6, 2, workProfileId_old); assertEquals(10, getItemCountForProfile(db, myProfileId_old)); assertEquals(6, getItemCountForProfile(db, workProfileId_old)); RestoreDbTask task = new RestoreDbTask(); - task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm); + task.sanitizeDB(mContext, controller, controller.getDb(), bm); // All the data has been migrated to the new user ids assertEquals(0, getItemCountForProfile(db, myProfileId_old)); @@ -173,12 +188,13 @@ public class RestoreDbTaskTest { assertEquals(10, getCount(db, "select * from favorites")); } - private void addIconsBulk(DatabaseHelper helper, int count, int screen, long profileId) { - int columns = LauncherAppState.getIDP(getInstrumentation().getTargetContext()).numColumns; + private void addIconsBulk(MyModelDbController controller, + int count, int screen, long profileId) { + int columns = LauncherAppState.getIDP(mContext).numColumns; String packageName = getInstrumentation().getContext().getPackageName(); for (int i = 0; i < count; i++) { ContentValues values = new ContentValues(); - values.put(LauncherSettings.Favorites._ID, helper.generateNewItemId()); + values.put(LauncherSettings.Favorites._ID, controller.generateNewItemId()); values.put(LauncherSettings.Favorites.CONTAINER, CONTAINER_DESKTOP); values.put(LauncherSettings.Favorites.SCREEN, screen); values.put(LauncherSettings.Favorites.CELLX, i % columns); @@ -189,11 +205,11 @@ public class RestoreDbTaskTest { values.put(LauncherSettings.Favorites.ITEM_TYPE, ITEM_TYPE_APPLICATION); values.put(LauncherSettings.Favorites.INTENT, new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0)); - helper.getWritableDatabase().insert(TABLE_NAME, null, values); + + controller.insert(TABLE_NAME, values); } } - @Test public void testRemoveScreenIdGaps_firstScreenEmpty() { runRemoveScreenIdGapsTest( @@ -216,7 +232,7 @@ public class RestoreDbTaskTest { } private void runRemoveScreenIdGapsTest(int[] screenIds, int[] expectedScreenIds) { - SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase(); + SQLiteDatabase db = new MyModelDbController(42).getDb(); // Add some mock data for (int i = 0; i < screenIds.length; i++) { ContentValues values = new ContentValues(); @@ -254,13 +270,12 @@ public class RestoreDbTaskTest { } } - private class MyDatabaseHelper extends DatabaseHelper { + private class MyModelDbController extends ModelDbController { - public final LongSparseArray<UserHandle> users; + public final LongSparseArray<UserHandle> users = new LongSparseArray<>(); - MyDatabaseHelper(long profileId) { - super(getInstrumentation().getTargetContext(), null, false); - users = new LongSparseArray<>(); + MyModelDbController(long profileId) { + super(mContext); users.put(profileId, myUserHandle()); } @@ -269,10 +284,5 @@ public class RestoreDbTaskTest { int index = users.indexOfValue(user); return index >= 0 ? users.keyAt(index) : -1; } - - @Override - protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { } - - protected void onEmptyDbCreated() { } } } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 3141c7ba12..d7c4ae3857 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -72,6 +72,7 @@ import com.android.launcher3.util.rule.SamplerRule; import com.android.launcher3.util.rule.ScreenRecordRule; import com.android.launcher3.util.rule.ShellCommandRule; import com.android.launcher3.util.rule.TestStabilityRule; +import com.android.launcher3.util.rule.ViewCaptureRule; import org.junit.After; import org.junit.Assert; @@ -215,14 +216,15 @@ public abstract class AbstractLauncherUiTest { } protected TestRule getRulesInsideActivityMonitor() { + final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(); final RuleChain inner = RuleChain .outerRule(new PortraitLandscapeRunner(this)) - .around(new FailureWatcher(mDevice, mLauncher)); + .around(viewCaptureRule) + .around(new FailureWatcher(mDevice, mLauncher, viewCaptureRule.getViewCapture())); return TestHelpers.isInLauncherProcess() - ? RuleChain.outerRule(ShellCommandRule.setDefaultLauncher()) - .around(inner) : - inner; + ? RuleChain.outerRule(ShellCommandRule.setDefaultLauncher()).around(inner) + : inner; } @Rule diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java index bf31e39ccc..976afcdd13 100644 --- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java +++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java @@ -113,7 +113,7 @@ public class LauncherModelHelper { private final HashMap<Class, HashMap<String, Field>> mFieldCache = new HashMap<>(); private final MockContentResolver mMockResolver = new MockContentResolver(); public final TestLauncherProvider provider; - public final SanboxModelContext sandboxContext; + public final SandboxModelContext sandboxContext; public final long defaultProfileId; @@ -128,7 +128,7 @@ public class LauncherModelHelper { Settings.Global.getString(context.getContentResolver(), "test"); provider = new TestLauncherProvider(); - sandboxContext = new SanboxModelContext(); + sandboxContext = new SandboxModelContext(); defaultProfileId = UserCache.INSTANCE.get(sandboxContext) .getSerialNumberForUser(Process.myUserHandle()); setupProvider(LauncherProvider.AUTHORITY, provider); @@ -363,12 +363,6 @@ public class LauncherModelHelper { sandboxContext.getContentResolver().insert(contentUri, values); } - public void deleteItem(int itemId, @NonNull final String tableName) { - final Uri uri = Uri.parse("content://" - + LauncherProvider.AUTHORITY + "/" + tableName + "/" + itemId); - sandboxContext.getContentResolver().delete(uri, null, null); - } - /** * Sets up a mock provider to load the provided layout by default, next time the layout loads */ @@ -426,7 +420,7 @@ public class LauncherModelHelper { } public SQLiteDatabase getDb() { - return getModelDbController().getDatabaseHelper().getWritableDatabase(); + return getModelDbController().getDb(); } } @@ -446,13 +440,13 @@ public class LauncherModelHelper { return success; } - public class SanboxModelContext extends SandboxContext { + public class SandboxModelContext extends SandboxContext { private final ArrayMap<String, Object> mSpiedServices = new ArrayMap<>(); private final PackageManager mPm; private final File mDbDir; - SanboxModelContext() { + SandboxModelContext() { super(ApplicationProvider.getApplicationContext(), UserCache.INSTANCE, InstallSessionHelper.INSTANCE, LauncherPrefs.INSTANCE, LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE, @@ -463,7 +457,7 @@ public class LauncherModelHelper { mDbDir = new File(getCacheDir(), UUID.randomUUID().toString()); } - public SanboxModelContext allow(MainThreadInitializedObject object) { + public SandboxModelContext allow(MainThreadInitializedObject object) { mAllowedObjects.add(object); return this; } diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java index 51facf49ab..19e7b13e33 100644 --- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java +++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java @@ -7,8 +7,12 @@ import android.os.FileUtils; import android.os.ParcelFileDescriptor.AutoCloseInputStream; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.test.core.app.ApplicationProvider; import androidx.test.uiautomator.UiDevice; +import com.android.app.viewcapture.ViewCapture; import com.android.launcher3.tapl.LauncherInstrumentation; import com.android.launcher3.ui.AbstractLauncherUiTest; @@ -29,10 +33,14 @@ public class FailureWatcher extends TestWatcher { private static boolean sSavedBugreport = false; final private UiDevice mDevice; private final LauncherInstrumentation mLauncher; + @NonNull + private final ViewCapture mViewCapture; - public FailureWatcher(UiDevice device, LauncherInstrumentation launcher) { + public FailureWatcher(UiDevice device, LauncherInstrumentation launcher, + @NonNull ViewCapture viewCapture) { mDevice = device; mLauncher = launcher; + mViewCapture = viewCapture; } @Override @@ -82,7 +90,7 @@ public class FailureWatcher extends TestWatcher { @Override protected void failed(Throwable e, Description description) { - onError(mLauncher, description, e); + onError(mLauncher, description, e, mViewCapture); } static File diagFile(Description description, String prefix, String ext) { @@ -93,8 +101,12 @@ public class FailureWatcher extends TestWatcher { public static void onError(LauncherInstrumentation launcher, Description description, Throwable e) { - final UiDevice device = launcher.getDevice(); - if (device == null) return; + onError(launcher, description, e, null); + } + + private static void onError(LauncherInstrumentation launcher, Description description, + Throwable e, @Nullable ViewCapture viewCapture) { + final File sceenshot = diagFile(description, "TestScreenshot", "png"); final File hierarchy = diagFile(description, "Hierarchy", "zip"); @@ -109,13 +121,20 @@ public class FailureWatcher extends TestWatcher { out.putNextEntry(new ZipEntry("visible_windows.zip")); dumpCommand("cmd window dump-visible-window-views", out); out.closeEntry(); - } catch (IOException ex) { + + if (viewCapture != null) { + out.putNextEntry(new ZipEntry("FS/data/misc/wmtrace/failed_test.vc")); + viewCapture.dumpTo(out, ApplicationProvider.getApplicationContext()); + out.closeEntry(); + } + } catch (Exception ignored) { } Log.e(TAG, "Failed test " + description.getMethodName() + ",\nscreenshot will be saved to " + sceenshot + ",\nUI dump at: " + hierarchy + " (use go/web-hv to open the dump file)", e); + final UiDevice device = launcher.getDevice(); device.takeScreenshot(sceenshot); // Dump accessibility hierarchy diff --git a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java index 2093682373..e9a52f84df 100644 --- a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java +++ b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java @@ -56,4 +56,4 @@ public class LauncherActivityRule extends SimpleActivityRule<Launcher> { return launcher.getWorkspace().getFirstMatch(op) != null; }; } -} +}
\ No newline at end of file diff --git a/tests/src/com/android/launcher3/util/rule/SimpleActivityRule.java b/tests/src/com/android/launcher3/util/rule/SimpleActivityRule.java index 1dbba6a1f6..2eedec30b6 100644 --- a/tests/src/com/android/launcher3/util/rule/SimpleActivityRule.java +++ b/tests/src/com/android/launcher3/util/rule/SimpleActivityRule.java @@ -102,4 +102,4 @@ public class SimpleActivityRule<T extends Activity> implements TestRule { } } } -} +}
\ No newline at end of file diff --git a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt new file mode 100644 index 0000000000..e4713b2e8b --- /dev/null +++ b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 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.launcher3.util.rule + +import android.app.Activity +import android.app.Application +import android.media.permission.SafeCloseable +import android.os.Bundle +import androidx.test.core.app.ApplicationProvider +import com.android.app.viewcapture.SimpleViewCapture +import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement + +/** + * This JUnit TestRule registers a listener for activity lifecycle events to attach a ViewCapture + * instance that other test rules use to dump the timelapse hierarchy upon an error during a test. + * + * This rule will not work in OOP tests that don't have access to the activity under test. + */ +class ViewCaptureRule : TestRule { + val viewCapture = SimpleViewCapture("test-view-capture") + + override fun apply(base: Statement, description: Description): Statement { + return object : Statement() { + override fun evaluate() { + val windowListenerCloseables = mutableListOf<SafeCloseable>() + + val lifecycleCallbacks = + object : ActivityLifecycleCallbacksAdapter { + override fun onActivityCreated(activity: Activity, bundle: Bundle?) { + super.onActivityCreated(activity, bundle) + windowListenerCloseables.add( + viewCapture.startCapture( + activity.window.decorView, + "${description.testClass?.simpleName}.${description.methodName}" + ) + ) + } + + override fun onActivityDestroyed(activity: Activity) { + super.onActivityDestroyed(activity) + viewCapture.stopCapture(activity.window.decorView) + } + } + + val application = ApplicationProvider.getApplicationContext<Application>() + application.registerActivityLifecycleCallbacks(lifecycleCallbacks) + + try { + base.evaluate() + } finally { + application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks) + + // Clean up ViewCapture references here rather than in onActivityDestroyed so + // test code can access view hierarchy capture. onActivityDestroyed would delete + // view capture data before FailureWatcher could output it as a test artifact. + windowListenerCloseables.onEach(SafeCloseable::close) + } + } + } + } +} |