chromium/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplierTest.java

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.tabmodel;

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

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;

import org.chromium.base.Callback;
import org.chromium.base.supplier.ObservableSupplierImpl;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.test.util.browser.tabmodel.MockTabModel;
import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector;

/** Unit tests for {@link TabModelSelectorProfileSupplierTest}. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class TabModelSelectorProfileSupplierTest {
    @Mock Profile mProfile;
    @Mock Profile mIncognitoProfile;
    @Mock Callback<Profile> mProfileCallback1;
    @Mock Callback<Profile> mProfileCallback2;

    ObservableSupplierImpl<TabModelSelector> mTabModelSelectorSupplier =
            new ObservableSupplierImpl<>();

    TabModelSelectorProfileSupplier mSupplier;
    MockTabModelSelector mSelector;
    MockTabModel mNormalModel;
    MockTabModel mIncognitoModel;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        initTabModelSelector();
        mSupplier = new TabModelSelectorProfileSupplier(mTabModelSelectorSupplier);
        doReturn(true).when(mIncognitoProfile).isOffTheRecord();
    }

    private void initTabModelSelector() {
        mSelector = new MockTabModelSelector(mProfile, mIncognitoProfile, 0, 0, null);
        mSelector.initializeTabModels(
                new EmptyTabModel() {
                    @Override
                    public boolean isActiveModel() {
                        return true;
                    }
                },
                new IncognitoTabModelImpl(null));
        mNormalModel = new MockTabModel(mProfile, null);
        mNormalModel.setActive(true);
        mIncognitoModel = new MockTabModel(mIncognitoProfile, null);
    }

    @Test
    public void testInitialTabModelHasNoProfile_initializedLater() {
        mTabModelSelectorSupplier.set(mSelector);
        Assert.assertFalse(mSupplier.hasValue());

        mSelector.initializeTabModels(mNormalModel, mIncognitoModel);
        mSelector.markTabStateInitialized();
        Assert.assertEquals(mProfile, mSupplier.get());
    }

    @Test
    public void testObserversFired() {
        mSupplier.addObserver(mProfileCallback1);
        mSupplier.addObserver(mProfileCallback2);

        mTabModelSelectorSupplier.set(mSelector);
        Assert.assertFalse(mSupplier.hasValue());
        mSelector.initializeTabModels(mNormalModel, mIncognitoModel);
        mSelector.markTabStateInitialized();

        Assert.assertEquals(mProfile, mSupplier.get());
        verify(mProfileCallback1, times(1)).onResult(mProfile);
        verify(mProfileCallback2, times(1)).onResult(mProfile);

        mSelector.selectModel(true);
        Assert.assertEquals(mIncognitoProfile, mSupplier.get());
        verify(mProfileCallback1, times(1)).onResult(mIncognitoProfile);
        verify(mProfileCallback2, times(1)).onResult(mIncognitoProfile);
    }

    @Test
    public void tesOTRProfileReturnsForIncognitoTabModel() {
        mTabModelSelectorSupplier.set(mSelector);
        mSelector.initializeTabModels(mNormalModel, mIncognitoModel);
        mSelector.markTabStateInitialized();
        mSelector.selectModel(true);

        Assert.assertEquals(mIncognitoProfile, mSupplier.get());
    }

    @Test
    public void tesRegularProfileReturnsForRegularTabModel() {
        mTabModelSelectorSupplier.set(mSelector);
        mSelector.initializeTabModels(mNormalModel, mIncognitoModel);
        mSelector.markTabStateInitialized();
        Assert.assertEquals(mProfile, mSupplier.get());

        mSelector.selectModel(true);
        Assert.assertEquals(mIncognitoProfile, mSupplier.get());

        mSelector.selectModel(false);
        Assert.assertEquals(mProfile, mSupplier.get());
    }

    @Test
    public void testDestroyPreInitialization() {
        mSupplier.destroy();

        mTabModelSelectorSupplier.set(mSelector);
        mSelector.initializeTabModels(mNormalModel, mIncognitoModel);
        mSelector.markTabStateInitialized();
        Assert.assertFalse(mSupplier.hasValue());
    }

    @Test
    public void testDestroyPostInitialization() {
        mTabModelSelectorSupplier.set(mSelector);
        mSupplier.destroy();

        mSelector.initializeTabModels(mNormalModel, mIncognitoModel);
        mSelector.markTabStateInitialized();
        Assert.assertFalse(mSupplier.hasValue());
    }

    @Test
    public void testPreviouslyInitializedSelector() {
        mSelector.initializeTabModels(mNormalModel, mIncognitoModel);
        mSelector.markTabStateInitialized();

        mTabModelSelectorSupplier.set(mSelector);

        Assert.assertEquals(mProfile, mSupplier.get());
    }

    @Test
    public void testSwapTabModelSelector() {
        mTabModelSelectorSupplier.set(mSelector);
        mSelector.initializeTabModels(mNormalModel, mIncognitoModel);
        mSelector.markTabStateInitialized();
        Assert.assertEquals(mProfile, mSupplier.get());

        Profile profile2 = mock(Profile.class);
        Profile incognitoProfile2 = mock(Profile.class);
        doReturn(true).when(incognitoProfile2).isOffTheRecord();
        MockTabModelSelector selector2 =
                new MockTabModelSelector(profile2, incognitoProfile2, 0, 0, null);
        MockTabModel normalModel2 = new MockTabModel(profile2, null);
        MockTabModel incognitoModel2 = new MockTabModel(incognitoProfile2, null);
        selector2.initializeTabModels(normalModel2, incognitoModel2);
        selector2.markTabStateInitialized();
        mTabModelSelectorSupplier.set(selector2);

        Assert.assertEquals(profile2, mSupplier.get());

        // Change the model on the no longer registered selector and ensure the profile does not
        // change.
        mSelector.selectModel(true);
        Assert.assertEquals(profile2, mSupplier.get());
        mSelector.selectModel(false);
        Assert.assertEquals(profile2, mSupplier.get());

        // Change the model on the registered selector and ensure the profile changes.
        selector2.selectModel(true);
        Assert.assertEquals(incognitoProfile2, mSupplier.get());
    }
}