Index: content/browser/browser_thread_unittest.cc |
diff --git a/content/browser/browser_thread_unittest.cc b/content/browser/browser_thread_unittest.cc |
index f3f37952ff73ea072dfd12e08bb9b0ff08bbaa18..0538819fa3d3bcecfb49604f1f679a9a83b99c70 100644 |
--- a/content/browser/browser_thread_unittest.cc |
+++ b/content/browser/browser_thread_unittest.cc |
@@ -7,9 +7,11 @@ |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
#include "base/location.h" |
+#include "base/message_loop/message_loop.h" |
#include "base/run_loop.h" |
#include "base/sequenced_task_runner_helpers.h" |
#include "base/single_thread_task_runner.h" |
+#include "base/threading/thread_task_runner_handle.h" |
#include "content/browser/browser_thread_impl.h" |
#include "content/public/test/test_browser_thread.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -25,6 +27,10 @@ class BrowserThreadTest : public testing::Test { |
base::MessageLoop::QuitWhenIdleClosure()); |
} |
+ void StopFileThread() { |
+ file_thread_->Stop(); |
+ } |
+ |
protected: |
void SetUp() override { |
ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI)); |
@@ -35,7 +41,7 @@ class BrowserThreadTest : public testing::Test { |
void TearDown() override { |
ui_thread_->Stop(); |
- file_thread_->Stop(); |
+ StopFileThread(); |
} |
static void BasicFunction(base::MessageLoop* message_loop) { |
@@ -72,6 +78,44 @@ class BrowserThreadTest : public testing::Test { |
mutable base::MessageLoop loop_; |
}; |
+class FileThreadDestructionObserver |
+ : public base::MessageLoop::DestructionObserver { |
+ public: |
+ explicit FileThreadDestructionObserver(bool* did_shutdown, |
+ const base::Closure& callback) |
+ : callback_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
+ callback_(callback), |
+ file_task_runner_( |
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)), |
+ did_shutdown_(did_shutdown) { |
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)->PostTask( |
+ FROM_HERE, base::Bind(&Watch, this)); |
+ } |
+ |
+ private: |
+ static void Watch(FileThreadDestructionObserver* observer) { |
+ base::MessageLoop::current()->AddDestructionObserver(observer); |
+ } |
+ |
+ // base::MessageLoop::DestructionObserver: |
+ void WillDestroyCurrentMessageLoop() override { |
+ // Ensure that even during MessageLoop teardown the BrowserThread ID is |
+ // correctly associated with this thread and the BrowserThreadTaskRunner |
+ // knows it's on the right thread. |
+ EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
+ EXPECT_TRUE(file_task_runner_->BelongsToCurrentThread()); |
+ |
+ base::MessageLoop::current()->RemoveDestructionObserver(this); |
+ *did_shutdown_ = true; |
+ callback_task_runner_->PostTask(FROM_HERE, callback_); |
+ } |
+ |
+ const scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_; |
+ const base::Closure callback_; |
+ const scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; |
+ bool* did_shutdown_; |
+}; |
+ |
TEST_F(BrowserThreadTest, PostTask) { |
BrowserThread::PostTask( |
BrowserThread::FILE, |
@@ -118,4 +162,16 @@ TEST_F(BrowserThreadTest, PostTaskAndReply) { |
base::RunLoop().Run(); |
} |
+TEST_F(BrowserThreadTest, RunsTasksOnCurrentThreadDuringShutdown) { |
+ bool did_shutdown = false; |
+ base::RunLoop loop; |
+ FileThreadDestructionObserver observer(&did_shutdown, loop.QuitClosure()); |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&BrowserThreadTest::StopFileThread, base::Unretained(this))); |
+ loop.Run(); |
+ |
+ EXPECT_TRUE(did_shutdown); |
+} |
+ |
} // namespace content |