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

Commit 71a48d9a authored by Sihua Ma's avatar Sihua Ma
Browse files

Add unit test for CustomWidgetManager

Number of methods covered: 5

Test: atest NexusLauncherRoboTests:CustomWidgetManagerTest
Test: SysUI studio
Flag: TEST_ONLY
Bug: 353303621
Change-Id: I69c9567391d3a874c7b2abcd473887194ec2dcfc
parent 72c4ebed
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.launcher3.R;
import com.android.launcher3.util.MainThreadInitializedObject;
@@ -45,6 +46,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;

@@ -62,9 +64,16 @@ public class CustomWidgetManager implements PluginListener<CustomWidgetPlugin>,
    private final HashMap<ComponentName, CustomWidgetPlugin> mPlugins;
    private final List<CustomAppWidgetProviderInfo> mCustomWidgets;
    private Consumer<PackageUserKey> mWidgetRefreshCallback;
    private final @NonNull AppWidgetManager mAppWidgetManager;

    private CustomWidgetManager(Context context) {
        this(context, AppWidgetManager.getInstance(context));
    }

    @VisibleForTesting
    CustomWidgetManager(Context context, @NonNull AppWidgetManager widgetManager) {
        mContext = context;
        mAppWidgetManager = widgetManager;
        mPlugins = new HashMap<>();
        mCustomWidgets = new ArrayList<>();
        PluginManagerWrapper.INSTANCE.get(context)
@@ -94,7 +103,7 @@ public class CustomWidgetManager implements PluginListener<CustomWidgetPlugin>,

    @Override
    public void onPluginConnected(CustomWidgetPlugin plugin, Context context) {
        List<AppWidgetProviderInfo> providers = AppWidgetManager.getInstance(context)
        List<AppWidgetProviderInfo> providers = mAppWidgetManager
                .getInstalledProvidersForProfile(Process.myUserHandle());
        if (providers.isEmpty()) return;
        Parcel parcel = Parcel.obtain();
@@ -113,6 +122,12 @@ public class CustomWidgetManager implements PluginListener<CustomWidgetPlugin>,
        mCustomWidgets.removeIf(w -> w.getComponent().equals(cn));
    }

    @VisibleForTesting
    @NonNull
    Map<ComponentName, CustomWidgetPlugin> getPlugins() {
        return mPlugins;
    }

    /**
     * Inject a callback function to refresh the widgets.
     */
+144 −0
Original line number Diff line number Diff line
/*
 * 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.launcher3.widget.custom

import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.os.Process
import android.platform.test.flag.junit.SetFlagsRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
import com.android.launcher3.util.PluginManagerWrapper
import com.android.launcher3.util.WidgetUtils
import com.android.launcher3.widget.LauncherAppWidgetHostView
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
import com.android.systemui.plugins.CustomWidgetPlugin
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.same
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

@SmallTest
@RunWith(AndroidJUnit4::class)
class CustomWidgetManagerTest {

    @get:Rule val setFlagsRule = SetFlagsRule()

    private val context = SandboxModelContext()
    private lateinit var underTest: CustomWidgetManager

    @Mock private lateinit var pluginManager: PluginManagerWrapper
    @Mock private lateinit var mockAppWidgetManager: AppWidgetManager

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        context.putObject(PluginManagerWrapper.INSTANCE, pluginManager)
        underTest = CustomWidgetManager(context, mockAppWidgetManager)
    }

    @After
    fun tearDown() {
        underTest.close()
    }

    @Test
    fun plugin_manager_added_after_initialization() {
        verify(pluginManager)
            .addPluginListener(same(underTest), same(CustomWidgetPlugin::class.java), eq(true))
    }

    @Test
    fun close_widget_manager_should_remove_plugin_listener() {
        underTest.close()
        verify(pluginManager).removePluginListener(same(underTest))
    }

    @Test
    fun on_plugin_connected_no_provider_info() {
        doReturn(emptyList<LauncherAppWidgetProviderInfo>())
            .whenever(mockAppWidgetManager)
            .getInstalledProvidersForProfile(any())
        val mockPlugin = mock(CustomWidgetPlugin::class.java)
        underTest.onPluginConnected(mockPlugin, context)
        assertEquals(0, underTest.plugins.size)
    }

    @Test
    fun on_plugin_connected_exist_provider_info() {
        doReturn(listOf(WidgetUtils.createAppWidgetProviderInfo(TEST_COMPONENT_NAME)))
            .whenever(mockAppWidgetManager)
            .getInstalledProvidersForProfile(eq(Process.myUserHandle()))
        val mockPlugin = mock(CustomWidgetPlugin::class.java)
        underTest.onPluginConnected(mockPlugin, context)
        assertEquals(1, underTest.plugins.size)
    }

    @Test
    fun on_plugin_disconnected() {
        doReturn(listOf(WidgetUtils.createAppWidgetProviderInfo(TEST_COMPONENT_NAME)))
            .whenever(mockAppWidgetManager)
            .getInstalledProvidersForProfile(eq(Process.myUserHandle()))
        val mockPlugin = mock(CustomWidgetPlugin::class.java)
        underTest.onPluginConnected(mockPlugin, context)
        underTest.onPluginDisconnected(mockPlugin)
        assertEquals(0, underTest.plugins.size)
    }

    @Test
    fun on_view_created() {
        val mockPlugin = mock(CustomWidgetPlugin::class.java)
        val mockWidgetView = mock(LauncherAppWidgetHostView::class.java)
        val mockProviderInfo = mock(CustomAppWidgetProviderInfo::class.java)
        doReturn(mockProviderInfo).whenever(mockWidgetView).appWidgetInfo
        mockProviderInfo.provider = TEST_COMPONENT_NAME
        underTest.plugins.put(TEST_COMPONENT_NAME, mockPlugin)
        underTest.onViewCreated(mockWidgetView)
        verify(mockPlugin).onViewCreated(eq(mockWidgetView))
    }

    @Test
    fun generate_stream() {
        assertTrue(underTest.stream().toList().isEmpty())
        doReturn(listOf(WidgetUtils.createAppWidgetProviderInfo(TEST_COMPONENT_NAME)))
            .whenever(mockAppWidgetManager)
            .getInstalledProvidersForProfile(eq(Process.myUserHandle()))
        val mockPlugin = mock(CustomWidgetPlugin::class.java)
        underTest.onPluginConnected(mockPlugin, context)
        assertEquals(1, underTest.stream().toList().size)
    }

    companion object {
        private const val TEST_CLASS = "TEST_CLASS"
        private val TEST_COMPONENT_NAME =
            ComponentName(getInstrumentation().targetContext.packageName, TEST_CLASS)
    }
}