blob: 9233eeead1f48022fb486a5ed66b136e8382fc3f [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/test/test_browser_thread_bundle.h"
#include "base/atomicops.h"
#include "base/bind_helpers.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::test::ScopedTaskEnvironment;
namespace content {
namespace {
// TestBrowserThreadBundleTest.RunUntilIdle will run kNumTasks tasks that will
// hop back-and-forth between TaskScheduler and UI thread kNumHops times.
// Note: These values are arbitrary.
constexpr int kNumHops = 13;
constexpr int kNumTasks = 8;
void PostTaskToUIThread(int iteration, base::subtle::Atomic32* tasks_run);
void PostToTaskScheduler(int iteration, base::subtle::Atomic32* tasks_run) {
// All iterations but the first come from a task that was posted.
if (iteration > 0)
base::subtle::NoBarrier_AtomicIncrement(tasks_run, 1);
if (iteration == kNumHops)
return;
base::PostTask(FROM_HERE,
base::BindOnce(&PostTaskToUIThread, iteration + 1, tasks_run));
}
void PostTaskToUIThread(int iteration, base::subtle::Atomic32* tasks_run) {
// All iterations but the first come from a task that was posted.
if (iteration > 0)
base::subtle::NoBarrier_AtomicIncrement(tasks_run, 1);
if (iteration == kNumHops)
return;
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PostToTaskScheduler, iteration + 1, tasks_run));
}
} // namespace
TEST(TestBrowserThreadBundleTest, RunUntilIdle) {
TestBrowserThreadBundle test_browser_thread_bundle;
base::subtle::Atomic32 tasks_run = 0;
// Post half the tasks on TaskScheduler and the other half on the UI thread
// so they cross and the last hops aren't all on the same task runner.
for (int i = 0; i < kNumTasks; ++i) {
if (i % 2) {
PostToTaskScheduler(0, &tasks_run);
} else {
PostTaskToUIThread(0, &tasks_run);
}
}
test_browser_thread_bundle.RunUntilIdle();
EXPECT_EQ(kNumTasks * kNumHops, base::subtle::NoBarrier_Load(&tasks_run));
}
namespace {
void PostRecurringTaskToIOThread(int iteration, int* tasks_run) {
// All iterations but the first come from a task that was posted.
if (iteration > 0)
(*tasks_run)++;
if (iteration == kNumHops)
return;
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PostRecurringTaskToIOThread, iteration + 1, tasks_run));
}
} // namespace
TEST(TestBrowserThreadBundleTest, RunIOThreadUntilIdle) {
TestBrowserThreadBundle test_browser_thread_bundle(
TestBrowserThreadBundle::Options::REAL_IO_THREAD);
int tasks_run = 0;
for (int i = 0; i < kNumTasks; ++i) {
PostRecurringTaskToIOThread(0, &tasks_run);
}
test_browser_thread_bundle.RunIOThreadUntilIdle();
EXPECT_EQ(kNumTasks * kNumHops, tasks_run);
}
TEST(TestBrowserThreadBundleTest, MessageLoopTypeMismatch) {
base::test::ScopedTaskEnvironment task_environment(
base::test::ScopedTaskEnvironment::MainThreadType::UI);
EXPECT_DEATH_IF_SUPPORTED(
{
TestBrowserThreadBundle test_browser_thread_bundle(
TestBrowserThreadBundle::IO_MAINLOOP);
},
"");
}
TEST(TestBrowserThreadBundleTest, MultipleTestBrowserThreadBundle) {
EXPECT_DEATH_IF_SUPPORTED(
{
TestBrowserThreadBundle test_browser_thread_bundle;
TestBrowserThreadBundle other_test_browser_thread_bundle;
},
"");
}
} // namespace content