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

Commit 55753796 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add FingerprintEnrollProgressViewModelTest"

parents d2b71ce4 af880ef7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
include /src/com/android/settings/biometrics/OWNERS
+179 −0
Original line number Diff line number Diff line
/*
 * 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.settings.biometrics2.ui.viewmodel;

import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
import static android.hardware.fingerprint.FingerprintManager.ENROLL_FIND_SENSOR;
import static android.hardware.fingerprint.FingerprintManager.EnrollReason;
import static android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;

import static com.android.settings.biometrics2.ui.model.EnrollmentProgress.INITIAL_STEPS;

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

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Application;
import android.content.res.Resources;
import android.os.CancellationSignal;

import com.android.settings.R;
import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.testutils.InstantTaskExecutorRule;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;

@RunWith(RobolectricTestRunner.class)
public class FingerprintEnrollProgressViewModelTest {

    @Rule public final MockitoRule mockito = MockitoJUnit.rule();
    @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();

    @Mock private Application mApplication;
    @Mock private Resources mResources;
    @Mock private FingerprintUpdater mFingerprintUpdater;

    private FingerprintEnrollProgressViewModel mViewModel;

    @Before
    public void setUp() {
        when(mApplication.getResources()).thenReturn(mResources);
        when(mResources.getBoolean(R.bool.enrollment_message_display_controller_flag))
                .thenReturn(false);
        mViewModel = new FingerprintEnrollProgressViewModel(mApplication, mFingerprintUpdater);
    }

    @Test
    public void testStartEnrollment() {
        @EnrollReason final int enrollReason = ENROLL_FIND_SENSOR;
        final int userId = 334;
        final byte[] token = new byte[] { 1, 2, 3 };
        mViewModel.setToken(token);
        mViewModel.setUserId(userId);

        // Start enrollment
        final boolean ret = mViewModel.startEnrollment(enrollReason);

        assertThat(ret).isTrue();
        verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
                eq(userId), any(EnrollmentCallback.class), eq(enrollReason));
    }

    @Test
    public void testStartEnrollmentFailBecauseOfNoToken() {
        // Start enrollment
        final boolean ret = mViewModel.startEnrollment(ENROLL_FIND_SENSOR);

        assertThat(ret).isFalse();
        verify(mFingerprintUpdater, never()).enroll(any(byte[].class),
                any(CancellationSignal.class), anyInt(), any(EnrollmentCallback.class), anyInt());
    }

    @Test
    public void testCancelEnrollment() {
        @EnrollReason final int enrollReason = ENROLL_ENROLL;
        final int userId = 334;
        final byte[] token = new byte[] { 1, 2, 3 };
        mViewModel.setToken(token);
        mViewModel.setUserId(userId);

        final TestWrapper<CancellationSignal> signalWrapper = new TestWrapper<>();
        doAnswer(invocation -> {
            signalWrapper.mValue = invocation.getArgument(1);
            return null;
        }).when(mFingerprintUpdater).enroll(any(byte[].class), any(CancellationSignal.class),
                eq(userId), any(EnrollmentCallback.class), anyInt());

        // Start enrollment
        final boolean ret = mViewModel.startEnrollment(enrollReason);
        assertThat(ret).isTrue();
        assertThat(signalWrapper.mValue).isNotNull();

        // Cancel enrollment
        mViewModel.cancelEnrollment();

        assertThat(signalWrapper.mValue.isCanceled()).isTrue();
    }

    @Test
    public void testProgressUpdate() {
        @EnrollReason final int enrollReason = ENROLL_ENROLL;
        final int userId = 334;
        final byte[] token = new byte[] { 1, 2, 3 };
        mViewModel.setToken(token);
        mViewModel.setUserId(userId);

        final TestWrapper<EnrollmentCallback> callbackWrapper = new TestWrapper<>();
        doAnswer(invocation -> {
            callbackWrapper.mValue = invocation.getArgument(3);
            return null;
        }).when(mFingerprintUpdater).enroll(any(byte[].class), any(CancellationSignal.class),
                eq(userId), any(EnrollmentCallback.class), anyInt());

        // Start enrollment
        final boolean ret = mViewModel.startEnrollment(enrollReason);
        assertThat(ret).isTrue();
        assertThat(callbackWrapper.mValue).isNotNull();

        // Update first progress
        callbackWrapper.mValue.onEnrollmentProgress(25);
        EnrollmentProgress progress = mViewModel.getProgressLiveData().getValue();
        assertThat(progress).isNotNull();
        assertThat(progress.getSteps()).isEqualTo(25);
        // TODO(b/260957933) verify getRemaining() when it is really used
        //assertThat(progress.getRemaining()).isEqualTo(25);

        // Update second progress
        callbackWrapper.mValue.onEnrollmentProgress(20);
        progress = mViewModel.getProgressLiveData().getValue();
        assertThat(progress).isNotNull();
        assertThat(progress.getSteps()).isEqualTo(25);
        // TODO(b/260957933) verify getRemaining() when it is really used
        //assertThat(progress.getRemaining()).isEqualTo(20);

        // Clear progress
        mViewModel.clearProgressLiveData();
        progress = mViewModel.getProgressLiveData().getValue();
        assertThat(progress).isNotNull();
        assertThat(progress.getSteps()).isEqualTo(INITIAL_STEPS);
        // TODO(b/260957933) verify getRemaining() when it is really used
        //assertThat(progress.getRemaining()).isEqualTo(INITIAL_REMAINING);
    }

    // TODO(b/260957933): FingerprintEnrollProgressViewModel::getErrorLiveData() and
    // FingerprintEnrollProgressViewModel::getHelpLiveData() doesn't built into apk because no one
    // uses it. We shall test it when new FingerprintEnrollEnrolling has used these 2 methods.

    private static class TestWrapper<T> {
        T mValue;
    }
}
+59 −0
Original line number Diff line number Diff line
/*
 * 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.settings.testutils;

import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.arch.core.executor.TaskExecutor;

import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

/**
 * A JUnit Test Rule that swaps the background executor used by the Architecture Components with a
 * different one which executes each task synchronously.
 *
 * We can't refer it in prebuilt androidX library.
 * Copied it from androidx/arch/core/executor/testing/InstantTaskExecutorRule.java
 */
public class InstantTaskExecutorRule extends TestWatcher {
    @Override
    protected void starting(Description description) {
        super.starting(description);
        ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
            @Override
            public void executeOnDiskIO(Runnable runnable) {
                runnable.run();
            }

            @Override
            public void postToMainThread(Runnable runnable) {
                runnable.run();
            }

            @Override
            public boolean isMainThread() {
                return true;
            }
        });
    }

    @Override
    protected void finished(Description description) {
        super.finished(description);
        ArchTaskExecutor.getInstance().setDelegate(null);
    }
}