// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/test/gmock_callback_support.h" #include #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using testing::_; using testing::ByRef; using testing::MockFunction; namespace base::test { using TestCallback = base::RepeatingCallback; using TestOnceCallback = base::OnceCallback; using TestOnceCallbackMove = base::OnceCallback, int* dst)>; void SetBool(const bool& src, bool* dst) { *dst = src; } void SetIntFromPtr(std::unique_ptr ptr, int* dst) { *dst = *ptr; } TEST(GmockCallbackSupportTest, IsNullCallback) { MockFunction check; EXPECT_CALL(check, Call(IsNullCallback())); check.Call(TestCallback()); } TEST(GmockCallbackSupportTest, IsNotNullCallback) { MockFunction check; EXPECT_CALL(check, Call(IsNotNullCallback())); check.Call(base::BindRepeating(&SetBool)); } TEST(GmockCallbackSupportTest, IsNullOnceCallback) { MockFunction mock; EXPECT_CALL(mock, Call(IsNullCallback())); mock.Call(TestOnceCallback()); } TEST(GmockCallbackSupportTest, IsNotNullOnceCallback) { MockFunction mock; EXPECT_CALL(mock, Call(IsNotNullCallback())); mock.Call(base::BindOnce(&SetBool)); } TEST(GmockCallbackSupportTest, RunClosure0) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call(IsNotNullCallback())).WillOnce(RunClosure<0>()); check.Call(base::BindRepeating(&SetBool, true, &dst)); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunClosureByRefNotReset) { // Check that RepeatingClosure isn't reset by RunClosure(). MockFunction check; bool dst = false; EXPECT_CALL(check, Call(IsNotNullCallback())).WillOnce(RunClosure<0>()); auto closure = base::BindRepeating(&SetBool, true, &dst); check.Call(closure); EXPECT_TRUE(dst); EXPECT_FALSE(closure.is_null()); } TEST(GmockCallbackSupportTest, RunCallback0) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call(IsNotNullCallback())) .WillOnce(RunCallback<0>(true, &dst)); check.Call(base::BindRepeating(&SetBool)); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunCallback1) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call(0, IsNotNullCallback())) .WillOnce(RunCallback<1>(true, &dst)); check.Call(0, base::BindRepeating(&SetBool)); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunCallbackPassByRef) { MockFunction check; bool dst = false; bool src = false; EXPECT_CALL(check, Call(IsNotNullCallback())) .WillOnce(RunCallback<0>(ByRef(src), &dst)); src = true; check.Call(base::BindRepeating(&SetBool)); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunCallbackPassByValue) { MockFunction check; bool dst = false; bool src = true; EXPECT_CALL(check, Call(IsNotNullCallback())) .WillOnce(RunCallback<0>(src, &dst)); src = false; check.Call(base::BindRepeating(&SetBool)); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunOnceClosure0) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call(IsNotNullCallback())).WillOnce(RunOnceClosure<0>()); check.Call(base::BindOnce(&SetBool, true, &dst)); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunOnceCallback0) { MockFunction check; bool dst = false; bool src = true; EXPECT_CALL(check, Call(IsNotNullCallback())) .WillOnce(RunOnceCallback<0>(src, &dst)); src = false; check.Call(base::BindOnce(&SetBool)); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunOnceCallbackTwice) { MockFunction check; bool dst = false; bool src = true; EXPECT_CALL(check, Call) .WillRepeatedly(RunOnceCallbackRepeatedly<0>(std::ref(src), &dst)); check.Call(base::BindOnce(&SetBool)); EXPECT_TRUE(dst); src = false; check.Call(base::BindOnce(&SetBool)); EXPECT_FALSE(dst); } TEST(GmockCallbackSupportTest, RunClosureValue) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call()) .WillOnce(RunClosure(base::BindRepeating(&SetBool, true, &dst))); check.Call(); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunClosureValueWithArgs) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call(true, 42)) .WillOnce(RunClosure(base::BindRepeating(&SetBool, true, &dst))); check.Call(true, 42); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunOnceClosureValue) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call()) .WillOnce(RunOnceClosure(base::BindOnce(&SetBool, true, &dst))); check.Call(); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunOnceClosureValueWithArgs) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call(true, 42)) .WillOnce(RunOnceClosure(base::BindOnce(&SetBool, true, &dst))); check.Call(true, 42); EXPECT_TRUE(dst); } TEST(GmockCallbackSupportTest, RunOnceClosureValueMultipleCall) { MockFunction check; bool dst = false; EXPECT_CALL(check, Call()) .WillRepeatedly(RunOnceClosure(base::BindOnce(&SetBool, true, &dst))); check.Call(); EXPECT_TRUE(dst); // Invoking the RunOnceClosure action more than once will trigger a // CHECK-failure. dst = false; EXPECT_DEATH_IF_SUPPORTED(check.Call(), ""); } TEST(GmockCallbackSupportTest, RunOnceCallbackWithMoveOnlyType) { MockFunction check; auto val = std::make_unique(42); int dst = 0; EXPECT_CALL(check, Call).WillOnce(RunOnceCallback<0>(std::move(val), &dst)); check.Call(base::BindOnce(&SetIntFromPtr)); EXPECT_EQ(dst, 42); EXPECT_FALSE(val); } TEST(GmockCallbackSupportTest, RunOnceCallbackMultipleTimesCrashes) { MockFunction check; bool value = true; bool dst = false; EXPECT_CALL(check, Call).WillRepeatedly(RunOnceCallback<0>(value, &dst)); EXPECT_FALSE(dst); check.Call(BindOnce(&SetBool)); EXPECT_TRUE(dst); // The first `Call` has invalidated the captured args. Attempting // to run `Call` again should result in a CHECK(). EXPECT_DEATH_IF_SUPPORTED(check.Call(BindOnce(&SetBool)), ""); } TEST(GmockCallbackSupportTest, RunOnceCallbackReturnsValue) { MockFunction)> check; EXPECT_CALL(check, Call).WillRepeatedly(RunOnceCallbackRepeatedly<0>(42)); EXPECT_EQ(43, check.Call(base::BindOnce([](int i) { return i + 1; }))); EXPECT_EQ(44, check.Call(base::BindOnce([](int i) { return i + 2; }))); EXPECT_EQ(45, check.Call(base::BindOnce([](int i) { return i + 3; }))); } TEST(GmockCallbackSupportTest, RunOnceCallbackReturnsValueMoveOnly) { MockFunction)>)> check; EXPECT_CALL(check, Call) .WillOnce(RunOnceCallback<0>(std::make_unique(42))); EXPECT_EQ(43, check.Call(base::BindOnce( [](std::unique_ptr i) { return *i + 1; }))); } TEST(GmockCallbackSupportTest, RunCallbackReturnsValue) { MockFunction)> check; EXPECT_CALL(check, Call).WillRepeatedly(RunCallback<0>(42)); EXPECT_EQ(43, check.Call(base::BindRepeating([](int i) { return i + 1; }))); EXPECT_EQ(44, check.Call(base::BindRepeating([](int i) { return i + 2; }))); EXPECT_EQ(45, check.Call(base::BindRepeating([](int i) { return i + 3; }))); } // Smoke test to validate that RunOnceCallback<> works with vectors of move-only // args. TEST(GmockCallbackSupportTest, VectorOfMoveOnlyArgs) { using VectorOfMoveOnly = std::vector>; MockFunction)> check; EXPECT_CALL(check, Call).WillOnce(RunOnceCallback<0>([] { return VectorOfMoveOnly(); }())); check.Call(base::DoNothing()); } } // namespace base::test