Index: base/sequenced_task_runner_unittest.cc |
diff --git a/base/sequenced_task_runner_unittest.cc b/base/sequenced_task_runner_unittest.cc |
index 93ac20f7190a15e991f581c4effd67f0fe5b4bf7..7451e1d7a421fbdab915429fc15ede77461990eb 100644 |
--- a/base/sequenced_task_runner_unittest.cc |
+++ b/base/sequenced_task_runner_unittest.cc |
@@ -5,6 +5,7 @@ |
#include "base/sequenced_task_runner.h" |
#include "base/bind.h" |
+#include "base/gtest_prod_util.h" |
#include "base/message_loop/message_loop.h" |
#include "base/run_loop.h" |
#include "base/threading/thread.h" |
@@ -13,60 +14,89 @@ |
namespace base { |
namespace { |
-struct DeleteCounter { |
- DeleteCounter(int* counter, scoped_refptr<SequencedTaskRunner> task_runner) |
- : counter_(counter), |
- task_runner_(std::move(task_runner)) { |
- } |
- ~DeleteCounter() { |
- ++*counter_; |
- EXPECT_TRUE(!task_runner_ || task_runner_->RunsTasksOnCurrentThread()); |
+class FlagOnDelete { |
+ public: |
+ FlagOnDelete(bool* deleted, |
+ scoped_refptr<SequencedTaskRunner> expected_deletion_sequence) |
+ : deleted_(deleted), |
+ expected_deletion_sequence_(std::move(expected_deletion_sequence)) {} |
+ |
+ private: |
+ friend class DeleteHelper<FlagOnDelete>; |
+ FRIEND_TEST_ALL_PREFIXES(SequencedTaskRunnerTest, |
+ OnTaskRunnerDeleterTargetStoppedEarly); |
+ |
+ ~FlagOnDelete() { |
+ EXPECT_FALSE(*deleted_); |
+ *deleted_ = true; |
+ if (expected_deletion_sequence_) |
+ EXPECT_TRUE(expected_deletion_sequence_->RunsTasksInCurrentSequence()); |
} |
- int* counter_; |
- scoped_refptr<SequencedTaskRunner> task_runner_; |
+ bool* deleted_; |
+ const scoped_refptr<SequencedTaskRunner> expected_deletion_sequence_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FlagOnDelete); |
}; |
-} // namespace |
+class SequencedTaskRunnerTest : public testing::Test { |
+ protected: |
+ SequencedTaskRunnerTest() : foreign_thread_("foreign") {} |
+ |
+ void SetUp() override { |
+ main_runner_ = message_loop_.task_runner(); |
-TEST(SequencedTaskRunnerTest, OnTaskRunnerDeleter) { |
- base::MessageLoop message_loop; |
- base::Thread thread("Foreign"); |
- thread.Start(); |
+ foreign_thread_.Start(); |
+ foreign_runner_ = foreign_thread_.task_runner(); |
+ } |
- scoped_refptr<SequencedTaskRunner> current_thread = |
- message_loop.task_runner(); |
- scoped_refptr<SequencedTaskRunner> foreign_thread = |
- thread.task_runner(); |
+ scoped_refptr<SequencedTaskRunner> main_runner_; |
+ scoped_refptr<SequencedTaskRunner> foreign_runner_; |
- using SequenceBoundUniquePtr = |
- std::unique_ptr<DeleteCounter, OnTaskRunnerDeleter>; |
+ Thread foreign_thread_; |
- int counter = 0; |
- SequenceBoundUniquePtr ptr(new DeleteCounter(&counter, current_thread), |
- OnTaskRunnerDeleter(current_thread)); |
- EXPECT_EQ(0, counter); |
- foreign_thread->PostTask( |
+ private: |
+ MessageLoop message_loop_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SequencedTaskRunnerTest); |
+}; |
+ |
+using SequenceBoundUniquePtr = |
+ std::unique_ptr<FlagOnDelete, OnTaskRunnerDeleter>; |
+ |
+TEST_F(SequencedTaskRunnerTest, OnTaskRunnerDeleterOnMainThread) { |
+ bool deleted_on_main_thread = false; |
+ SequenceBoundUniquePtr ptr( |
+ new FlagOnDelete(&deleted_on_main_thread, main_runner_), |
+ OnTaskRunnerDeleter(main_runner_)); |
+ EXPECT_FALSE(deleted_on_main_thread); |
+ foreign_runner_->PostTask( |
FROM_HERE, BindOnce([](SequenceBoundUniquePtr) {}, Passed(&ptr))); |
{ |
RunLoop run_loop; |
- foreign_thread->PostTaskAndReply(FROM_HERE, BindOnce([] {}), |
- run_loop.QuitClosure()); |
+ foreign_runner_->PostTaskAndReply(FROM_HERE, BindOnce([] {}), |
+ run_loop.QuitClosure()); |
run_loop.Run(); |
} |
- EXPECT_EQ(1, counter); |
+ EXPECT_TRUE(deleted_on_main_thread); |
+} |
- DeleteCounter* raw = new DeleteCounter(&counter, nullptr); |
- SequenceBoundUniquePtr ptr2(raw, OnTaskRunnerDeleter(foreign_thread)); |
- EXPECT_EQ(1, counter); |
+TEST_F(SequencedTaskRunnerTest, OnTaskRunnerDeleterTargetStoppedEarly) { |
+ bool deleted_on_main_thread = false; |
+ FlagOnDelete* raw = new FlagOnDelete(&deleted_on_main_thread, main_runner_); |
+ SequenceBoundUniquePtr ptr(raw, OnTaskRunnerDeleter(foreign_runner_)); |
+ EXPECT_FALSE(deleted_on_main_thread); |
- thread.Stop(); |
- ptr2 = nullptr; |
- ASSERT_EQ(1, counter); |
+ // Stopping the target ahead of deleting |ptr| should make its |
+ // OnTaskRunnerDeleter no-op. |
+ foreign_thread_.Stop(); |
+ ptr = nullptr; |
+ EXPECT_FALSE(deleted_on_main_thread); |
delete raw; |
- EXPECT_EQ(2, counter); |
+ EXPECT_TRUE(deleted_on_main_thread); |
} |
+} // namespace |
} // namespace base |