123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- // Copyright 2020 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 "base/task/bind_post_task.h"
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/sequence_checker_impl.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/test/task_environment.h"
- #include "base/threading/sequenced_task_runner_handle.h"
- #include "base/threading/thread.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace base {
- namespace {
- void SetBool(bool* variable, bool value) {
- *variable = value;
- }
- void SetInt(int* variable, int value) {
- *variable = value;
- }
- void SetIntFromUniquePtr(int* variable, std::unique_ptr<int> value) {
- *variable = *value;
- }
- int Multiply(int value) {
- return value * 5;
- }
- void ClearReference(OnceClosure callback) {}
- class SequenceRestrictionChecker {
- public:
- explicit SequenceRestrictionChecker(bool& set_on_destroy)
- : set_on_destroy_(set_on_destroy) {}
- ~SequenceRestrictionChecker() {
- EXPECT_TRUE(checker_.CalledOnValidSequence());
- set_on_destroy_ = true;
- }
- void Run() { EXPECT_TRUE(checker_.CalledOnValidSequence()); }
- private:
- SequenceCheckerImpl checker_;
- bool& set_on_destroy_;
- };
- } // namespace
- class BindPostTaskTest : public testing::Test {
- protected:
- test::SingleThreadTaskEnvironment task_environment_;
- scoped_refptr<SequencedTaskRunner> task_runner_ =
- SequencedTaskRunnerHandle::Get();
- };
- TEST_F(BindPostTaskTest, OnceClosure) {
- bool val = false;
- OnceClosure cb = BindOnce(&SetBool, &val, true);
- OnceClosure post_cb = BindPostTask(task_runner_, std::move(cb));
- std::move(post_cb).Run();
- EXPECT_FALSE(val);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(val);
- }
- TEST_F(BindPostTaskTest, OnceCallback) {
- OnceCallback<void(bool*, bool)> cb = BindOnce(&SetBool);
- OnceCallback<void(bool*, bool)> post_cb =
- BindPostTask(task_runner_, std::move(cb));
- bool val = false;
- std::move(post_cb).Run(&val, true);
- EXPECT_FALSE(val);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(val);
- }
- TEST_F(BindPostTaskTest, OnceWithBoundMoveOnlyArg) {
- int val = 0;
- OnceClosure cb =
- BindOnce(&SetIntFromUniquePtr, &val, std::make_unique<int>(10));
- OnceClosure post_cb = BindPostTask(task_runner_, std::move(cb));
- std::move(post_cb).Run();
- EXPECT_EQ(val, 0);
- RunLoop().RunUntilIdle();
- EXPECT_EQ(val, 10);
- }
- TEST_F(BindPostTaskTest, OnceWithUnboundMoveOnlyArg) {
- int val = 0;
- OnceCallback<void(std::unique_ptr<int>)> cb =
- BindOnce(&SetIntFromUniquePtr, &val);
- OnceCallback<void(std::unique_ptr<int>)> post_cb =
- BindPostTask(task_runner_, std::move(cb));
- std::move(post_cb).Run(std::make_unique<int>(10));
- EXPECT_EQ(val, 0);
- RunLoop().RunUntilIdle();
- EXPECT_EQ(val, 10);
- }
- TEST_F(BindPostTaskTest, OnceWithIgnoreResult) {
- OnceCallback<void(int)> post_cb =
- BindPostTask(task_runner_, BindOnce(IgnoreResult(&Multiply)));
- std::move(post_cb).Run(1);
- RunLoop().RunUntilIdle();
- }
- TEST_F(BindPostTaskTest, OnceThen) {
- int value = 0;
- // Multiply() returns an int and SetInt() takes an int as a parameter.
- OnceClosure then_cb =
- BindOnce(&Multiply, 5)
- .Then(BindPostTask(task_runner_, BindOnce(&SetInt, &value)));
- std::move(then_cb).Run();
- EXPECT_EQ(value, 0);
- RunLoop().RunUntilIdle();
- EXPECT_EQ(value, 25);
- }
- // Ensure that the input callback is run/destroyed on the correct thread even if
- // the callback returned from BindPostTask() is run on a different thread.
- TEST_F(BindPostTaskTest, OnceRunDestroyedOnBound) {
- Thread target_thread("testing");
- ASSERT_TRUE(target_thread.Start());
- // SequenceRestrictionChecker checks it's creation, Run() and deletion all
- // happen on the main thread.
- bool destroyed = false;
- auto checker = std::make_unique<SequenceRestrictionChecker>(destroyed);
- // `checker` is owned by `cb` which is wrapped in `post_cb`. `post_cb` is run
- // on a different thread which triggers a PostTask() back to the test main
- // thread to invoke `cb` which runs SequenceRestrictionChecker::Run(). After
- // `cb` has been invoked `checker` is destroyed along with the BindState.
- OnceClosure cb =
- BindOnce(&SequenceRestrictionChecker::Run, std::move(checker));
- OnceClosure post_cb = BindPostTask(task_runner_, std::move(cb));
- target_thread.task_runner()->PostTask(FROM_HERE, std::move(post_cb));
- target_thread.FlushForTesting();
- EXPECT_FALSE(destroyed);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(destroyed);
- }
- // Ensure that the input callback is destroyed on the correct thread even if the
- // callback returned from BindPostTask() is destroyed without being run on a
- // different thread.
- TEST_F(BindPostTaskTest, OnceNotRunDestroyedOnBound) {
- Thread target_thread("testing");
- ASSERT_TRUE(target_thread.Start());
- // SequenceRestrictionChecker checks it's creation and deletion all happen on
- // the test main thread.
- bool destroyed = false;
- auto checker = std::make_unique<SequenceRestrictionChecker>(destroyed);
- // `checker` is owned by `cb` which is wrapped in `post_cb`. `post_cb` is
- // deleted on a different thread which triggers a PostTask() back to the test
- // main thread to destroy `cb` and `checker`.
- OnceClosure cb =
- BindOnce(&SequenceRestrictionChecker::Run, std::move(checker));
- OnceClosure post_cb = BindPostTask(task_runner_, std::move(cb));
- target_thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&ClearReference, std::move(post_cb)));
- target_thread.FlushForTesting();
- EXPECT_FALSE(destroyed);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(destroyed);
- }
- TEST_F(BindPostTaskTest, RepeatingClosure) {
- bool val = false;
- RepeatingClosure cb = BindRepeating(&SetBool, &val, true);
- RepeatingClosure post_cb = BindPostTask(task_runner_, std::move(cb));
- post_cb.Run();
- EXPECT_FALSE(val);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(val);
- val = false;
- post_cb.Run();
- EXPECT_FALSE(val);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(val);
- }
- TEST_F(BindPostTaskTest, RepeatingCallback) {
- RepeatingCallback<void(bool*, bool)> cb = BindRepeating(&SetBool);
- RepeatingCallback<void(bool*, bool)> post_cb =
- BindPostTask(task_runner_, std::move(cb));
- bool val = false;
- post_cb.Run(&val, true);
- EXPECT_FALSE(val);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(val);
- post_cb.Run(&val, false);
- EXPECT_TRUE(val);
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(val);
- }
- TEST_F(BindPostTaskTest, RepeatingWithUnboundMoveOnlyArg) {
- int val = 0;
- RepeatingCallback<void(std::unique_ptr<int>)> cb =
- BindRepeating(&SetIntFromUniquePtr, &val);
- RepeatingCallback<void(std::unique_ptr<int>)> post_cb =
- BindPostTask(task_runner_, std::move(cb));
- post_cb.Run(std::make_unique<int>(10));
- EXPECT_EQ(val, 0);
- RunLoop().RunUntilIdle();
- EXPECT_EQ(val, 10);
- post_cb.Run(std::make_unique<int>(20));
- EXPECT_EQ(val, 10);
- RunLoop().RunUntilIdle();
- EXPECT_EQ(val, 20);
- }
- TEST_F(BindPostTaskTest, RepeatingWithIgnoreResult) {
- RepeatingCallback<void(int)> post_cb =
- BindPostTask(task_runner_, BindRepeating(IgnoreResult(&Multiply)));
- std::move(post_cb).Run(1);
- RunLoop().RunUntilIdle();
- }
- TEST_F(BindPostTaskTest, RepeatingThen) {
- int value = 0;
- // Multiply() returns an int and SetInt() takes an int as a parameter.
- RepeatingCallback<void(int)> then_cb = BindRepeating(&Multiply).Then(
- BindPostTask(task_runner_, BindRepeating(&SetInt, &value)));
- then_cb.Run(5);
- EXPECT_EQ(value, 0);
- RunLoop().RunUntilIdle();
- EXPECT_EQ(value, 25);
- then_cb.Run(10);
- EXPECT_EQ(value, 25);
- RunLoop().RunUntilIdle();
- EXPECT_EQ(value, 50);
- }
- // Ensure that the input callback is run/destroyed on the correct thread even if
- // the callback returned from BindPostTask() is run on a different thread.
- TEST_F(BindPostTaskTest, RepeatingRunDestroyedOnBound) {
- Thread target_thread("testing");
- ASSERT_TRUE(target_thread.Start());
- // SequenceRestrictionChecker checks it's creation, Run() and deletion all
- // happen on the main thread.
- bool destroyed = false;
- auto checker = std::make_unique<SequenceRestrictionChecker>(destroyed);
- // `checker` is owned by `cb` which is wrapped in `post_cb`. `post_cb` is run
- // on a different thread which triggers a PostTask() back to the test main
- // thread to invoke `cb` which runs SequenceRestrictionChecker::Run(). After
- // `cb` has been invoked `checker` is destroyed along with the BindState.
- RepeatingClosure cb =
- BindRepeating(&SequenceRestrictionChecker::Run, std::move(checker));
- RepeatingClosure post_cb = BindPostTask(task_runner_, std::move(cb));
- target_thread.task_runner()->PostTask(FROM_HERE, std::move(post_cb));
- target_thread.FlushForTesting();
- EXPECT_FALSE(destroyed);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(destroyed);
- }
- // Ensure that the input callback is destroyed on the correct thread even if the
- // callback returned from BindPostTask() is destroyed without being run on a
- // different thread.
- TEST_F(BindPostTaskTest, RepeatingNotRunDestroyedOnBound) {
- Thread target_thread("testing");
- ASSERT_TRUE(target_thread.Start());
- // SequenceRestrictionChecker checks it's creation and deletion all happen on
- // the test main thread.
- bool destroyed = false;
- auto checker = std::make_unique<SequenceRestrictionChecker>(destroyed);
- // `checker` is owned by `cb` which is wrapped in `post_cb`. `post_cb` is
- // deleted on a different thread which triggers a PostTask() back to the test
- // main thread to destroy `cb` and `checker`.
- RepeatingClosure cb =
- BindRepeating(&SequenceRestrictionChecker::Run, std::move(checker));
- RepeatingClosure post_cb = BindPostTask(task_runner_, std::move(cb));
- target_thread.task_runner()->PostTask(
- FROM_HERE, BindRepeating(&ClearReference, std::move(post_cb)));
- target_thread.FlushForTesting();
- EXPECT_FALSE(destroyed);
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(destroyed);
- }
- } // namespace base
|