// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ios/web/public/test/web_task_environment.h"
#include <memory>
#include "base/notreached.h"
#include "base/run_loop.h"
#include "ios/web/public/test/test_web_thread.h"
#include "ios/web/web_thread_impl.h"
namespace web {
namespace {
// Returns the base::TaskEnvironment::MainThreadType corresponding to
// `main_thread_type`.
base::test::TaskEnvironment::MainThreadType ConvertMainThreadType(
WebTaskEnvironment::MainThreadType main_thread_type) {
switch (main_thread_type) {
case WebTaskEnvironment::MainThreadType::UI:
return base::test::TaskEnvironment::MainThreadType::UI;
case WebTaskEnvironment::MainThreadType::IO:
return base::test::TaskEnvironment::MainThreadType::IO;
}
NOTREACHED();
}
} // namespace
WebTaskEnvironment::WebTaskEnvironment(TimeSource time_source,
MainThreadType main_thread_type,
IOThreadType io_thread_type,
base::trait_helpers::NotATraitTag tag)
: TaskEnvironment(time_source, ConvertMainThreadType(main_thread_type)),
io_thread_type_(io_thread_type) {
WebThreadImpl::CreateTaskExecutor();
ui_thread_ =
std::make_unique<TestWebThread>(WebThread::UI, GetMainThreadTaskRunner());
if (io_thread_type_ != IOThreadType::REAL_THREAD_DELAYED) {
StartIOThreadInternal();
}
}
WebTaskEnvironment::~WebTaskEnvironment() {
// To ensure a clean teardown, each thread's message loop must be flushed
// just before the thread is destroyed. But stopping a fake thread does not
// automatically flush the message loop, so do it manually.
// See http://crbug.com/247525 for discussion.
base::RunLoop().RunUntilIdle();
if (io_thread_) {
io_thread_->Stop();
}
base::RunLoop().RunUntilIdle();
ui_thread_->Stop();
base::RunLoop().RunUntilIdle();
// This is required to ensure that all remaining MessageLoop and ThreadPool
// tasks run in an atomic step. This is a bit different than production
// where the main thread is not flushed after it's done running but this
// approach is preferred in unit tests as running more tasks can merely
// uncover more issues (e.g. if a bad tasks is posted but never blocked upon
// it could make a test flaky whereas by flushing, the test will always
// fail).
RunUntilIdle();
WebThreadImpl::ResetTaskExecutorForTesting();
}
void WebTaskEnvironment::StartIOThread() {
DCHECK_EQ(io_thread_type_, IOThreadType::REAL_THREAD_DELAYED);
StartIOThreadInternal();
}
void WebTaskEnvironment::StartIOThreadInternal() {
DCHECK(!io_thread_);
if (io_thread_type_ == IOThreadType::FAKE_THREAD) {
io_thread_ = std::make_unique<TestWebThread>(WebThread::IO,
GetMainThreadTaskRunner());
} else {
io_thread_ = std::make_unique<TestWebThread>(WebThread::IO);
io_thread_->StartIOThread();
}
}
} // namespace web