Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fc16ab2 authored by Stefan Andonian's avatar Stefan Andonian Committed by Android (Google) Code Review
Browse files

Merge "Add unit tests for LoaderTask" into main

parents f5099749 4c7d7d67
Loading
Loading
Loading
Loading
+145 −0

File added.

Preview size limit exceeded, changes collapsed.

+79 −0

File added.

Preview size limit exceeded, changes collapsed.

+64 −0
Original line number Original line Diff line number Diff line
package com.android.launcher3.model

import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import androidx.test.platform.app.InstrumentationRegistry
import java.io.BufferedReader
import java.io.InputStreamReader

private val All_COLUMNS =
    arrayOf(
        "_id",
        "title",
        "intent",
        "container",
        "screen",
        "cellX",
        "cellY",
        "spanX",
        "spanY",
        "itemType",
        "appWidgetId",
        "icon",
        "appWidgetProvider",
        "modified",
        "restored",
        "profileId",
        "rank",
        "options",
        "appWidgetSource"
    )
private const val INSERTION_STATEMENT_FILE = "databases/workspace_items.sql"

class FactitiousDbController(context: Context) : ModelDbController(context) {

    private val inMemoryDb: SQLiteDatabase by lazy {
        SQLiteDatabase.createInMemory(SQLiteDatabase.OpenParams.Builder().build()).also { db ->
            BufferedReader(
                    InputStreamReader(
                        InstrumentationRegistry.getInstrumentation()
                            .context
                            .assets
                            .open(INSERTION_STATEMENT_FILE)
                    )
                )
                .lines()
                .forEach { sqlStatement -> db.execSQL(sqlStatement) }
        }
    }

    override fun query(
        table: String,
        projection: Array<out String>?,
        selection: String?,
        selectionArgs: Array<out String>?,
        sortOrder: String?
    ): Cursor {
        return inMemoryDb.query(table, All_COLUMNS, selection, selectionArgs, null, null, sortOrder)
    }

    override fun loadDefaultFavoritesIfNecessary() {
        // No-Op
    }
}
+104 −0
Original line number Original line Diff line number Diff line
package com.android.launcher3.model

import android.appwidget.AppWidgetManager
import android.os.UserHandle
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.LauncherAppState
import com.android.launcher3.LauncherModel
import com.android.launcher3.LauncherModel.LoaderTransaction
import com.android.launcher3.icons.IconCache
import com.android.launcher3.icons.cache.CachingLogic
import com.android.launcher3.icons.cache.IconCacheUpdateHandler
import com.android.launcher3.util.Executors.MODEL_EXECUTOR
import com.android.launcher3.util.LooperIdleLock
import com.google.common.truth.Truth
import java.util.concurrent.CountDownLatch
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.Mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations

@SmallTest
@RunWith(AndroidJUnit4::class)
class LoaderTaskTest {
    @Mock private lateinit var app: LauncherAppState
    @Mock private lateinit var bgAllAppsList: AllAppsList
    @Mock private lateinit var modelDelegate: ModelDelegate
    @Mock private lateinit var launcherBinder: LauncherBinder
    @Mock private lateinit var launcherModel: LauncherModel
    @Mock private lateinit var transaction: LoaderTransaction
    @Mock private lateinit var iconCache: IconCache
    @Mock private lateinit var idleLock: LooperIdleLock
    @Mock private lateinit var iconCacheUpdateHandler: IconCacheUpdateHandler
    @Mock private lateinit var appWidgetManager: AppWidgetManager

    @Before
    fun setup() {
        val context = InstrumentationRegistry.getInstrumentation().targetContext
        val idp =
            InvariantDeviceProfile.INSTANCE[context].apply {
                numRows = 5
                numColumns = 6
                numDatabaseHotseatIcons = 5
            }

        MockitoAnnotations.initMocks(this)
        `when`(app.context).thenReturn(context)
        `when`(app.model).thenReturn(launcherModel)
        `when`(launcherModel.beginLoader(any(LoaderTask::class.java))).thenReturn(transaction)
        `when`(app.iconCache).thenReturn(iconCache)
        `when`(launcherModel.modelDbController).thenReturn(FactitiousDbController(context))
        `when`(app.invariantDeviceProfile).thenReturn(idp)
        `when`(launcherBinder.newIdleLock(any(LoaderTask::class.java))).thenReturn(idleLock)
        `when`(idleLock.awaitLocked(1000)).thenReturn(false)
        `when`(iconCache.updateHandler).thenReturn(iconCacheUpdateHandler)
        `when`(appWidgetManager.getInstalledProvidersForProfile(any(UserHandle::class.java)))
            .thenReturn(emptyList())
    }

    @Test
    fun loadsDataProperly() =
        with(BgDataModel()) {
            LoaderTask(app, bgAllAppsList, this, modelDelegate, launcherBinder)
                .runSyncOnBackgroundThread()
            Truth.assertThat(workspaceItems.size).isAtLeast(25)
            Truth.assertThat(appWidgets.size).isAtLeast(7)
            Truth.assertThat(folders.size()).isAtLeast(8)
            Truth.assertThat(itemsIdMap.size()).isAtLeast(45)
        }

    @Test
    fun bindsLoadedDataCorrectly() {
        LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder)
            .runSyncOnBackgroundThread()

        verify(launcherBinder).bindWorkspace(true, false)
        verify(modelDelegate).workspaceLoadComplete()
        verify(modelDelegate).loadAndBindAllAppsItems(any(), any(), any())
        verify(launcherBinder).bindAllApps()
        verify(iconCacheUpdateHandler, times(4)).updateIcons(any(), any<CachingLogic<Any>>(), any())
        verify(launcherBinder).bindDeepShortcuts()
        verify(launcherBinder).bindWidgets()
        verify(modelDelegate).loadAndBindOtherItems(any())
        verify(iconCacheUpdateHandler).finish()
        verify(modelDelegate).modelLoadComplete()
        verify(transaction).commit()
    }
}

private fun LoaderTask.runSyncOnBackgroundThread() {
    val latch = CountDownLatch(1)
    MODEL_EXECUTOR.execute {
        run()
        latch.countDown()
    }
    latch.await()
}