1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/task/post_job.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <atomic>
8*6777b538SAndroid Build Coastguard Worker #include <iterator>
9*6777b538SAndroid Build Coastguard Worker #include <numeric>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/barrier_closure.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/test/bind.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/test/gtest_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/test/task_environment.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/test/test_timeouts.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/test/test_waitable_event.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
18*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
19*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace base {
22*6777b538SAndroid Build Coastguard Worker
TEST(PostJobTest,PostJobSimple)23*6777b538SAndroid Build Coastguard Worker TEST(PostJobTest, PostJobSimple) {
24*6777b538SAndroid Build Coastguard Worker test::TaskEnvironment task_environment;
25*6777b538SAndroid Build Coastguard Worker std::atomic_size_t num_tasks_to_run(4);
26*6777b538SAndroid Build Coastguard Worker auto handle = PostJob(
27*6777b538SAndroid Build Coastguard Worker FROM_HERE, {},
28*6777b538SAndroid Build Coastguard Worker BindLambdaForTesting([&](JobDelegate* delegate) { --num_tasks_to_run; }),
29*6777b538SAndroid Build Coastguard Worker BindLambdaForTesting(
30*6777b538SAndroid Build Coastguard Worker [&](size_t /*worker_count*/) -> size_t { return num_tasks_to_run; }));
31*6777b538SAndroid Build Coastguard Worker handle.Join();
32*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(num_tasks_to_run, 0U);
33*6777b538SAndroid Build Coastguard Worker }
34*6777b538SAndroid Build Coastguard Worker
TEST(PostJobTest,CreateJobSimple)35*6777b538SAndroid Build Coastguard Worker TEST(PostJobTest, CreateJobSimple) {
36*6777b538SAndroid Build Coastguard Worker test::TaskEnvironment task_environment;
37*6777b538SAndroid Build Coastguard Worker std::atomic_size_t num_tasks_to_run(4);
38*6777b538SAndroid Build Coastguard Worker TestWaitableEvent threads_continue;
39*6777b538SAndroid Build Coastguard Worker RepeatingClosure barrier = BarrierClosure(
40*6777b538SAndroid Build Coastguard Worker num_tasks_to_run, BindLambdaForTesting([&threads_continue]() {
41*6777b538SAndroid Build Coastguard Worker threads_continue.Signal();
42*6777b538SAndroid Build Coastguard Worker }));
43*6777b538SAndroid Build Coastguard Worker bool job_started = false;
44*6777b538SAndroid Build Coastguard Worker auto handle =
45*6777b538SAndroid Build Coastguard Worker CreateJob(FROM_HERE, {}, BindLambdaForTesting([&](JobDelegate* delegate) {
46*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(job_started);
47*6777b538SAndroid Build Coastguard Worker barrier.Run();
48*6777b538SAndroid Build Coastguard Worker threads_continue.Wait();
49*6777b538SAndroid Build Coastguard Worker --num_tasks_to_run;
50*6777b538SAndroid Build Coastguard Worker }),
51*6777b538SAndroid Build Coastguard Worker BindLambdaForTesting([&](size_t /*worker_count*/) -> size_t {
52*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(job_started);
53*6777b538SAndroid Build Coastguard Worker return num_tasks_to_run;
54*6777b538SAndroid Build Coastguard Worker }));
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker PlatformThread::Sleep(TestTimeouts::tiny_timeout());
57*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(num_tasks_to_run, 4U);
58*6777b538SAndroid Build Coastguard Worker job_started = true;
59*6777b538SAndroid Build Coastguard Worker handle.Join();
60*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(num_tasks_to_run, 0U);
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker // Verify that concurrent accesses with task_id as the only form of
64*6777b538SAndroid Build Coastguard Worker // synchronisation doesn't trigger a race.
TEST(PostJobTest,TaskIds)65*6777b538SAndroid Build Coastguard Worker TEST(PostJobTest, TaskIds) {
66*6777b538SAndroid Build Coastguard Worker static constexpr size_t kNumConcurrentThreads = 2;
67*6777b538SAndroid Build Coastguard Worker static constexpr size_t kNumTasksToRun = 1000;
68*6777b538SAndroid Build Coastguard Worker base::test::TaskEnvironment task_environment;
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Worker size_t concurrent_array[kNumConcurrentThreads] = {0};
71*6777b538SAndroid Build Coastguard Worker std::atomic_size_t remaining_tasks{kNumTasksToRun};
72*6777b538SAndroid Build Coastguard Worker base::JobHandle handle = base::PostJob(
73*6777b538SAndroid Build Coastguard Worker FROM_HERE, {}, BindLambdaForTesting([&](base::JobDelegate* job) {
74*6777b538SAndroid Build Coastguard Worker uint8_t id = job->GetTaskId();
75*6777b538SAndroid Build Coastguard Worker size_t& slot = concurrent_array[id];
76*6777b538SAndroid Build Coastguard Worker slot++;
77*6777b538SAndroid Build Coastguard Worker --remaining_tasks;
78*6777b538SAndroid Build Coastguard Worker }),
79*6777b538SAndroid Build Coastguard Worker BindLambdaForTesting([&remaining_tasks](size_t) {
80*6777b538SAndroid Build Coastguard Worker return std::min(remaining_tasks.load(), kNumConcurrentThreads);
81*6777b538SAndroid Build Coastguard Worker }));
82*6777b538SAndroid Build Coastguard Worker handle.Join();
83*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kNumTasksToRun, std::accumulate(std::begin(concurrent_array),
84*6777b538SAndroid Build Coastguard Worker std::end(concurrent_array), 0U));
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker } // namespace base
88