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

Commit 649a1980 authored by Nergi Rahardi's avatar Nergi Rahardi Committed by Android (Google) Code Review
Browse files

Merge "Rewrite ResolutionPreferenceFragmentTest to kotlin" into main

parents fad73360 8d38149a
Loading
Loading
Loading
Loading
+0 −243
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.settings.connecteddevice.display;

import static android.view.Display.INVALID_DISPLAY;

import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.DISPLAY_MODE_LIMIT_OVERRIDE_PROP;
import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE;
import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.MORE_OPTIONS_KEY;
import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.TOP_OPTIONS_KEY;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.content.res.Resources;
import android.util.Pair;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.settingslib.widget.SelectorWithWidgetPreference;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;

/** Unit tests for {@link ResolutionPreferenceFragment}.  */
@RunWith(AndroidJUnit4.class)
public class ResolutionPreferenceFragmentTest extends ExternalDisplayTestBase {
    @Nullable
    private ResolutionPreferenceFragment mFragment;
    private int mPreferenceIdFromResource;
    private int mDisplayIdArg = INVALID_DISPLAY;
    @Mock
    private MetricsLogger mMockedMetricsLogger;

    @Test
    @UiThreadTest
    public void testCreateAndStart() {
        initFragment();
        mHandler.flush();
        assertThat(mPreferenceIdFromResource).isEqualTo(
                EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE);
        var pref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY);
        assertThat(pref).isNull();
        pref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY);
        assertThat(pref).isNull();
    }

    @Test
    @UiThreadTest
    public void testCreateAndStartDefaultDisplayNotAllowed() {
        mDisplayIdArg = 0;
        initFragment();
        mHandler.flush();
        var pref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY);
        assertThat(pref).isNull();
        pref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY);
        assertThat(pref).isNull();
    }

    @Test
    @UiThreadTest
    public void testModePreferences_modeLimitFlagIsOn_noOverride() {
        doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
        doReturn(null).when(mMockedInjector).getSystemProperty(
                DISPLAY_MODE_LIMIT_OVERRIDE_PROP);
        var topAndMorePref = runTestModePreferences();
        PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second;
        assertThat(topPref.getPreferenceCount()).isEqualTo(3);
        assertThat(morePref.getPreferenceCount()).isEqualTo(1);
    }

    @Test
    @UiThreadTest
    public void testModePreferences_noModeLimitFlag_overrideIsTrue() {
        doReturn(false).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
        doReturn("true").when(mMockedInjector).getSystemProperty(
                DISPLAY_MODE_LIMIT_OVERRIDE_PROP);
        var topAndMorePref = runTestModePreferences();
        PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second;
        assertThat(topPref.getPreferenceCount()).isEqualTo(3);
        assertThat(morePref.getPreferenceCount()).isEqualTo(1);
    }

    @Test
    @UiThreadTest
    public void testModePreferences_noModeLimitFlag_noOverride() {
        doReturn(false).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
        doReturn(null).when(mMockedInjector).getSystemProperty(
                DISPLAY_MODE_LIMIT_OVERRIDE_PROP);
        var topAndMorePref = runTestModePreferences();
        PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second;
        assertThat(topPref.getPreferenceCount()).isEqualTo(3);
        assertThat(morePref.getPreferenceCount()).isEqualTo(2);
    }

    @Test
    @UiThreadTest
    public void testModePreferences_modeLimitFlagIsOn_butOverrideIsFalse() {
        doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled();
        doReturn("false").when(mMockedInjector).getSystemProperty(
                DISPLAY_MODE_LIMIT_OVERRIDE_PROP);
        var topAndMorePref = runTestModePreferences();
        PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second;
        assertThat(topPref.getPreferenceCount()).isEqualTo(3);
        assertThat(morePref.getPreferenceCount()).isEqualTo(2);
    }

    @Test
    @UiThreadTest
    public void testModeChange() {
        DisplayDevice display = mDisplays.get(0);
        mDisplayIdArg = display.getId();
        initFragment();
        mHandler.flush();
        PreferenceCategory topPref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY);
        assertThat(topPref).isNotNull();
        var modePref = (SelectorWithWidgetPreference) topPref.getPreference(1);
        modePref.onClick();
        var mode = display.getSupportedModes().get(1);
        verify(mMockedInjector).setUserPreferredDisplayMode(mDisplayIdArg, mode);
    }

    private Pair<PreferenceCategory, PreferenceCategory> runTestModePreferences() {
        mDisplayIdArg = 1;
        initFragment();
        mHandler.flush();
        PreferenceCategory topPref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY);
        assertThat(topPref).isNotNull();
        PreferenceCategory morePref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY);
        assertThat(morePref).isNotNull();
        return new Pair<>(topPref, morePref);
    }

    private void initFragment() {
        if (mFragment != null) {
            return;
        }
        mFragment = new TestableResolutionPreferenceFragment();
        mFragment.onCreateCallback(null);
        mFragment.onActivityCreatedCallback(null);
        mFragment.onStartCallback();
    }

    private class TestableResolutionPreferenceFragment extends ResolutionPreferenceFragment {
        private final View mMockedRootView;
        private final TextView mEmptyView;
        private final Resources mMockedResources;
        private final MetricsLogger mLogger;
        TestableResolutionPreferenceFragment() {
            super(mMockedInjector);
            mMockedResources = mock(Resources.class);
            doReturn(61).when(mMockedResources).getInteger(
                    com.android.internal.R.integer.config_externalDisplayPeakRefreshRate);
            doReturn(1920).when(mMockedResources).getInteger(
                    com.android.internal.R.integer.config_externalDisplayPeakWidth);
            doReturn(1080).when(mMockedResources).getInteger(
                    com.android.internal.R.integer.config_externalDisplayPeakHeight);
            doReturn(true).when(mMockedResources).getBoolean(
                    com.android.internal.R.bool.config_refreshRateSynchronizationEnabled);
            mMockedRootView = mock(View.class);
            mEmptyView = new TextView(mContext);
            doReturn(mEmptyView).when(mMockedRootView).findViewById(android.R.id.empty);
            mLogger = mMockedMetricsLogger;
        }

        @Override
        public PreferenceScreen getPreferenceScreen() {
            return mPreferenceScreen;
        }

        @Override
        public View getView() {
            return mMockedRootView;
        }

        @Override
        public void setEmptyView(View view) {
            assertThat(view).isEqualTo(mEmptyView);
        }

        @Override
        public View getEmptyView() {
            return mEmptyView;
        }

        @Override
        public void addPreferencesFromResource(int resource) {
            mPreferenceIdFromResource = resource;
        }

        @Override
        protected int getDisplayIdArg() {
            return mDisplayIdArg;
        }

        @Override
        protected void writePreferenceClickMetric(Preference preference) {
            mLogger.writePreferenceClickMetric(preference);
        }

        @Override
        @NonNull
        protected Resources getResources(@NonNull Context context) {
            return mMockedResources;
        }
    }

    /**
     * Interface allowing to mock and spy on log events.
     */
    public interface MetricsLogger {
        /**
         * On preference click metric
         */
        void writePreferenceClickMetric(Preference preference);
    }
}
+219 −0
Original line number Diff line number Diff line
/*
 * Copyright 2025 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.settings.connecteddevice.display

import android.content.Context
import android.content.res.Resources
import android.view.Display.INVALID_DISPLAY
import android.view.View
import android.widget.TextView
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceScreen
import androidx.test.annotation.UiThreadTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.DISPLAY_MODE_LIMIT_OVERRIDE_PROP
import com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE
import com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.MORE_OPTIONS_KEY
import com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.TOP_OPTIONS_KEY
import com.android.settingslib.widget.SelectorWithWidgetPreference
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify

/** Unit tests for [ResolutionPreferenceFragment]. */
@RunWith(AndroidJUnit4::class)
class ResolutionPreferenceFragmentTest : ExternalDisplayTestBase() {

    private lateinit var fragment: ResolutionPreferenceFragment
    @Mock private lateinit var mockedMetricsLogger: MetricsLogger

    private var preferenceIdFromResource: Int = 0
    private var displayId: Int = INVALID_DISPLAY

    @Test
    @UiThreadTest
    fun testCreateAndStart() {
        initFragment()
        mHandler.flush()
        assertThat(preferenceIdFromResource)
            .isEqualTo(EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE)
        var pref = mPreferenceScreen.findPreference<Preference>(TOP_OPTIONS_KEY)
        assertThat(pref).isNull()
        pref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY)
        assertThat(pref).isNull()
    }

    @Test
    @UiThreadTest
    fun testCreateAndStartDefaultDisplayNotAllowed() {
        displayId = 0
        initFragment()
        mHandler.flush()
        var pref = mPreferenceScreen.findPreference<Preference>(TOP_OPTIONS_KEY)
        assertThat(pref).isNull()
        pref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY)
        assertThat(pref).isNull()
    }

    @Test
    @UiThreadTest
    fun testModePreferences_modeLimitFlagIsOn_noOverride() {
        doReturn(true).`when`(mMockedInjector).isModeLimitForExternalDisplayEnabled()
        doReturn(null).`when`(mMockedInjector).getSystemProperty(DISPLAY_MODE_LIMIT_OVERRIDE_PROP)
        val (topPref, morePref) = runTestModePreferences()
        assertThat(topPref.preferenceCount).isEqualTo(3)
        assertThat(morePref.preferenceCount).isEqualTo(1)
    }

    @Test
    @UiThreadTest
    fun testModePreferences_noModeLimitFlag_overrideIsTrue() {
        doReturn(false).`when`(mMockedInjector).isModeLimitForExternalDisplayEnabled()
        doReturn("true").`when`(mMockedInjector).getSystemProperty(DISPLAY_MODE_LIMIT_OVERRIDE_PROP)
        val (topPref, morePref) = runTestModePreferences()
        assertThat(topPref.preferenceCount).isEqualTo(3)
        assertThat(morePref.preferenceCount).isEqualTo(1)
    }

    @Test
    @UiThreadTest
    fun testModePreferences_noModeLimitFlag_noOverride() {
        doReturn(false).`when`(mMockedInjector).isModeLimitForExternalDisplayEnabled()
        doReturn(null).`when`(mMockedInjector).getSystemProperty(DISPLAY_MODE_LIMIT_OVERRIDE_PROP)
        val (topPref, morePref) = runTestModePreferences()
        assertThat(topPref.preferenceCount).isEqualTo(3)
        assertThat(morePref.preferenceCount).isEqualTo(2)
    }

    @Test
    @UiThreadTest
    fun testModePreferences_modeLimitFlagIsOn_butOverrideIsFalse() {
        doReturn(true).`when`(mMockedInjector).isModeLimitForExternalDisplayEnabled()
        doReturn("false")
            .`when`(mMockedInjector)
            .getSystemProperty(DISPLAY_MODE_LIMIT_OVERRIDE_PROP)
        val (topPref, morePref) = runTestModePreferences()
        assertThat(topPref.preferenceCount).isEqualTo(3)
        assertThat(morePref.preferenceCount).isEqualTo(2)
    }

    @Test
    @UiThreadTest
    fun testModeChange() {
        val display = mDisplays[0]
        displayId = display.id
        initFragment()
        mHandler.flush()
        val topPref = mPreferenceScreen.findPreference<PreferenceCategory>(TOP_OPTIONS_KEY)
        assertThat(topPref).isNotNull()
        val modePref = topPref!!.getPreference(1) as SelectorWithWidgetPreference
        modePref.onClick()
        val mode = display.supportedModes[1]
        verify(mMockedInjector).setUserPreferredDisplayMode(displayId, mode)
    }

    private fun runTestModePreferences(): Pair<PreferenceCategory, PreferenceCategory> {
        displayId = 1
        initFragment()
        mHandler.flush()
        val topPref = mPreferenceScreen.findPreference<PreferenceCategory>(TOP_OPTIONS_KEY)
        assertThat(topPref).isNotNull()
        val morePref = mPreferenceScreen.findPreference<PreferenceCategory>(MORE_OPTIONS_KEY)
        assertThat(morePref).isNotNull()
        return Pair(topPref!!, morePref!!)
    }

    private fun initFragment() {
        if (::fragment.isInitialized) {
            return
        }
        fragment = TestableResolutionPreferenceFragment()
        fragment.onCreateCallback(null)
        fragment.onActivityCreatedCallback(null)
        fragment.onStartCallback()
    }

    private inner class TestableResolutionPreferenceFragment :
        ResolutionPreferenceFragment(mMockedInjector) {
        private val mockRootView: View
        private val emptyView: TextView
        private val mockResources: Resources = mock(Resources::class.java)
        private val logger: MetricsLogger

        init {
            doReturn(61)
                .`when`(mockResources)
                .getInteger(com.android.internal.R.integer.config_externalDisplayPeakRefreshRate)
            doReturn(1920)
                .`when`(mockResources)
                .getInteger(com.android.internal.R.integer.config_externalDisplayPeakWidth)
            doReturn(1080)
                .`when`(mockResources)
                .getInteger(com.android.internal.R.integer.config_externalDisplayPeakHeight)
            doReturn(true)
                .`when`(mockResources)
                .getBoolean(com.android.internal.R.bool.config_refreshRateSynchronizationEnabled)
            mockRootView = mock(View::class.java)
            emptyView = TextView(mContext)
            doReturn(emptyView).`when`(mockRootView).findViewById<View>(android.R.id.empty)
            logger = mockedMetricsLogger
        }

        override fun getPreferenceScreen(): PreferenceScreen {
            return super@ResolutionPreferenceFragmentTest.mPreferenceScreen
        }

        override fun getView(): View {
            return mockRootView
        }

        override fun setEmptyView(view: View?) {
            assertThat(view).isEqualTo(emptyView)
        }

        override fun getEmptyView(): View {
            return emptyView
        }

        override fun addPreferencesFromResource(resource: Int) {
            preferenceIdFromResource = resource
        }

        override fun getDisplayIdArg(): Int {
            return displayId
        }

        override fun writePreferenceClickMetric(preference: Preference) {
            logger.writePreferenceClickMetric(preference)
        }

        override fun getResources(context: Context): Resources {
            return mockResources
        }
    }

    /** Interface allowing to mock and spy on log events. */
    interface MetricsLogger {
        /** On preference click metric */
        fun writePreferenceClickMetric(preference: Preference)
    }
}