chromium/components/download/network/android/junit/src/org/chromium/components/download/NetworkStatusListenerAndroidTest.java

// Copyright 2021 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.components.download;

import static org.mockito.Mockito.when;

import androidx.test.filters.SmallTest;

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

import org.chromium.base.ThreadUtils;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.JniMocker;
import org.chromium.net.ConnectionType;
import org.chromium.net.NetworkChangeNotifierAutoDetect;

/** Unit test for {@link NetworkStatusListenerAndroid} and {@link BackgroundNetworkStatusListener}. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class NetworkStatusListenerAndroidTest {
    private static final int NATIVE_PTR = 1;

    @Rule public JniMocker mJniMocker = new JniMocker();
    @Mock private NetworkChangeNotifierAutoDetect mAutoDetect;
    @Mock NetworkChangeNotifierAutoDetect.NetworkState mNetworkState;
    @Mock private NetworkStatusListenerAndroid.Natives mNativeMock;

    private NetworkStatusListenerAndroid mListener;

    private static class TestAutoDetectFactory
            extends BackgroundNetworkStatusListener.AutoDetectFactory {
        private NetworkChangeNotifierAutoDetect mAutoDetect;

        TestAutoDetectFactory(NetworkChangeNotifierAutoDetect autoDetect) {
            mAutoDetect = autoDetect;
        }

        // AutoDetectFactory overrides.
        @Override
        public NetworkChangeNotifierAutoDetect create(
                NetworkChangeNotifierAutoDetect.Observer observer,
                NetworkChangeNotifierAutoDetect.RegistrationPolicy policy) {
            return mAutoDetect;
        }
    }

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        BackgroundNetworkStatusListener.setAutoDetectFactory(
                new TestAutoDetectFactory(mAutoDetect));
        mJniMocker.mock(NetworkStatusListenerAndroidJni.TEST_HOOKS, mNativeMock);
    }

    private void runBackgroundThread() {
        // Flush any UI thread tasks first.
        ShadowLooper.runUiThreadTasks();

        // Run the background thread.
        ShadowLooper shadowLooper =
                Shadows.shadowOf(
                        NetworkStatusListenerAndroid.getHelperForTesting()
                                .getHandlerForTesting()
                                .getLooper());
        shadowLooper.runToEndOfTasks();

        // Flush any UI thread tasks created by the background thread.
        ShadowLooper.runUiThreadTasks();
    }

    private void initWithConnectionType(@ConnectionType int connectionType) {
        when(mAutoDetect.getCurrentNetworkState()).thenReturn(mNetworkState);
        when(mNetworkState.getConnectionType()).thenReturn(connectionType);
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mListener = NetworkStatusListenerAndroid.create(NATIVE_PTR);
                });
    }

    @Test
    @SmallTest
    public void testGetCurrentConnectionType() {
        initWithConnectionType(ConnectionType.CONNECTION_3G);

        runBackgroundThread();

        // The background thread should set the connection type correctly and update the main
        // thread.
        Assert.assertEquals(ConnectionType.CONNECTION_3G, mListener.getCurrentConnectionType());
    }

    @Test
    @SmallTest
    public void testOnConnectionTypeChanged() {
        initWithConnectionType(ConnectionType.CONNECTION_3G);

        runBackgroundThread();

        Assert.assertEquals(ConnectionType.CONNECTION_3G, mListener.getCurrentConnectionType());

        // Change the connection type on main thread, the connection type should be updated.
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    NetworkStatusListenerAndroid.getHelperForTesting()
                            .onConnectionTypeChanged(ConnectionType.CONNECTION_5G);
                });

        runBackgroundThread();

        Assert.assertEquals(ConnectionType.CONNECTION_5G, mListener.getCurrentConnectionType());
    }
}