// Copyright 2017 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.init;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.android.util.concurrent.RoboExecutorService;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.LooperMode;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.LoaderErrors;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.base.task.PostTask;
import org.chromium.base.task.test.ShadowAsyncTask;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.components.variations.firstrun.VariationsSeedFetcher;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/** Tests for {@link AsyncInitTaskRunner} */
@RunWith(BaseRobolectricTestRunner.class)
@Config(
manifest = Config.NONE,
shadows = {ShadowAsyncTask.class})
@LooperMode(LooperMode.Mode.LEGACY)
public class AsyncInitTaskRunnerTest {
private LibraryLoader mLoader;
private AsyncInitTaskRunner mRunner;
private CountDownLatch mLatch;
private VariationsSeedFetcher mVariationsSeedFetcher;
public AsyncInitTaskRunnerTest() {
LibraryLoader.getInstance().setLibraryProcessType(LibraryProcessType.PROCESS_BROWSER);
mLoader = spy(LibraryLoader.getInstance());
doNothing().when(mLoader).ensureInitialized();
LibraryLoader.setLibraryLoaderForTesting(mLoader);
mVariationsSeedFetcher = mock(VariationsSeedFetcher.class);
VariationsSeedFetcher.setVariationsSeedFetcherForTesting(mVariationsSeedFetcher);
PostTask.setPrenativeThreadPoolExecutorForTesting(new RoboExecutorService());
mLatch = new CountDownLatch(1);
mRunner =
spy(
new AsyncInitTaskRunner() {
@Override
protected void onSuccess() {
mLatch.countDown();
}
@Override
protected void onFailure(Exception failureCause) {
mLatch.countDown();
}
@Override
protected Executor getTaskPerThreadExecutor() {
return new RoboExecutorService();
}
});
// Allow test to run on all builds
when(mRunner.shouldFetchVariationsSeedDuringFirstRun()).thenReturn(true);
doNothing().when(mRunner).prefetchLibrary();
}
@Test
public void libraryLoaderOnlyTest() throws InterruptedException {
mRunner.startBackgroundTasks(false, false);
Robolectric.flushBackgroundThreadScheduler();
Robolectric.flushForegroundThreadScheduler();
assertTrue(mLatch.await(0, TimeUnit.SECONDS));
verify(mLoader).ensureInitialized();
verify(mRunner).onSuccess();
verify(mVariationsSeedFetcher, never()).fetchSeed(anyString(), anyString(), anyString());
}
@Test
public void libraryLoaderFailTest() throws InterruptedException {
Exception failureCause = new ProcessInitException(LoaderErrors.NATIVE_LIBRARY_LOAD_FAILED);
doThrow(failureCause).when(mLoader).ensureInitialized();
mRunner.startBackgroundTasks(false, false);
Robolectric.flushBackgroundThreadScheduler();
Robolectric.flushForegroundThreadScheduler();
assertTrue(mLatch.await(0, TimeUnit.SECONDS));
verify(mRunner).onFailure(failureCause);
verify(mVariationsSeedFetcher, never()).fetchSeed(anyString(), anyString(), anyString());
}
@Test
public void fetchVariationsTest() throws InterruptedException {
mRunner.startBackgroundTasks(false, true);
Robolectric.flushBackgroundThreadScheduler();
Robolectric.flushForegroundThreadScheduler();
assertTrue(mLatch.await(0, TimeUnit.SECONDS));
verify(mLoader).ensureInitialized();
verify(mRunner).onSuccess();
verify(mVariationsSeedFetcher).fetchSeed(anyString(), anyString(), anyString());
}
// TODO(aberent) Test for allocateChildConnection. Needs refactoring of ChildProcessLauncher to
// make it mockable.
}