// Copyright 2024 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/functional/concurrent_callbacks.h" #include #include "base/functional/callback.h" #include "base/test/gtest_util.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace { TEST(ConcurrentCallbacksTest, Empty) { test::SingleThreadTaskEnvironment task_environment; ConcurrentCallbacks concurrent; test::TestFuture> future; std::move(concurrent).Done(future.GetCallback()); std::vector values = future.Take(); EXPECT_TRUE(values.empty()); } TEST(ConcurrentCallbacksTest, RunBeforeDone) { test::SingleThreadTaskEnvironment task_environment; ConcurrentCallbacks concurrent; for (size_t i = 0; i < 10; ++i) { concurrent.CreateCallback().Run(i); } test::TestFuture> future; std::move(concurrent).Done(future.GetCallback()); EXPECT_FALSE(future.IsReady()); std::vector values = future.Take(); EXPECT_EQ(values.size(), 10u); for (size_t i = 0; i < values.size(); ++i) { EXPECT_EQ(values[i], i); } } TEST(ConcurrentCallbacksTest, RunAfterDone) { test::SingleThreadTaskEnvironment task_environment; ConcurrentCallbacks concurrent; std::vector> callbacks; for (size_t i = 0; i < 10; ++i) { callbacks.push_back(concurrent.CreateCallback()); } test::TestFuture> future; std::move(concurrent).Done(future.GetCallback()); for (size_t i = 0; i < callbacks.size(); ++i) { std::move(callbacks[i]).Run(i); } EXPECT_FALSE(future.IsReady()); std::vector values = future.Take(); EXPECT_EQ(values.size(), 10u); for (size_t i = 0; i < values.size(); ++i) { EXPECT_EQ(values[i], i); } } TEST(ConcurrentCallbacksTest, CallbacksOutliveObject) { test::SingleThreadTaskEnvironment task_environment; std::vector> callbacks; test::TestFuture> future; { ConcurrentCallbacks concurrent; for (size_t i = 0; i < 10; ++i) { callbacks.push_back(concurrent.CreateCallback()); } std::move(concurrent).Done(future.GetCallback()); } for (size_t i = 0; i < callbacks.size(); ++i) { std::move(callbacks[i]).Run(i); } EXPECT_FALSE(future.IsReady()); std::vector values = future.Take(); EXPECT_EQ(values.size(), 10u); for (size_t i = 0; i < values.size(); ++i) { EXPECT_EQ(values[i], i); } } TEST(ConcurrentCallbacksTest, CallbackAcceptsConstRef) { test::SingleThreadTaskEnvironment task_environment; ConcurrentCallbacks concurrent; std::vector> callbacks; for (size_t i = 0; i < 10; ++i) { callbacks.push_back(concurrent.CreateCallback()); } test::TestFuture> future; std::move(concurrent).Done(future.GetCallback()); for (size_t i = 0; i < callbacks.size(); ++i) { std::move(callbacks[i]).Run(i); } EXPECT_FALSE(future.IsReady()); std::vector values = future.Take(); EXPECT_EQ(values.size(), 10u); for (size_t i = 0; i < values.size(); ++i) { EXPECT_EQ(values[i], i); } } } // namespace } // namespace base