[M85 Dev][EFL] Fix crashes at webview launch
[platform/framework/web/chromium-efl.git] / base / deferred_sequenced_task_runner_unittest.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/deferred_sequenced_task_runner.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback_forward.h"
10 #include "base/location.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/test/task_environment.h"
15 #include "base/threading/thread.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace base {
21 namespace {
22
23 class DeferredSequencedTaskRunnerTest : public testing::Test {
24  public:
25   class ExecuteTaskOnDestructor : public RefCounted<ExecuteTaskOnDestructor> {
26    public:
27     ExecuteTaskOnDestructor(
28         DeferredSequencedTaskRunnerTest* executor,
29         int task_id)
30         : executor_(executor),
31           task_id_(task_id) {
32     }
33   private:
34    friend class RefCounted<ExecuteTaskOnDestructor>;
35    virtual ~ExecuteTaskOnDestructor() { executor_->ExecuteTask(task_id_); }
36    DeferredSequencedTaskRunnerTest* executor_;
37    int task_id_;
38   };
39
40   void ExecuteTask(int task_id) {
41     AutoLock lock(lock_);
42     executed_task_ids_.push_back(task_id);
43   }
44
45   void PostExecuteTask(int task_id) {
46     runner_->PostTask(FROM_HERE,
47                       BindOnce(&DeferredSequencedTaskRunnerTest::ExecuteTask,
48                                Unretained(this), task_id));
49   }
50
51   void StartRunner() {
52     runner_->Start();
53   }
54
55   void DoNothing(ExecuteTaskOnDestructor* object) {
56   }
57
58  protected:
59   DeferredSequencedTaskRunnerTest()
60       : runner_(
61             new DeferredSequencedTaskRunner(ThreadTaskRunnerHandle::Get())) {}
62
63   test::TaskEnvironment task_environment_;
64   scoped_refptr<DeferredSequencedTaskRunner> runner_;
65   mutable Lock lock_;
66   std::vector<int> executed_task_ids_;
67 };
68
69 TEST_F(DeferredSequencedTaskRunnerTest, Stopped) {
70   PostExecuteTask(1);
71   RunLoop().RunUntilIdle();
72   EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
73 }
74
75 TEST_F(DeferredSequencedTaskRunnerTest, Start) {
76   StartRunner();
77   PostExecuteTask(1);
78   RunLoop().RunUntilIdle();
79   EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
80 }
81
82 TEST_F(DeferredSequencedTaskRunnerTest, StartWithMultipleElements) {
83   StartRunner();
84   for (int i = 1; i < 5; ++i)
85     PostExecuteTask(i);
86
87   RunLoop().RunUntilIdle();
88   EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4));
89 }
90
91 TEST_F(DeferredSequencedTaskRunnerTest, DeferredStart) {
92   PostExecuteTask(1);
93   RunLoop().RunUntilIdle();
94   EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
95
96   StartRunner();
97   RunLoop().RunUntilIdle();
98   EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
99
100   PostExecuteTask(2);
101   RunLoop().RunUntilIdle();
102   EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2));
103 }
104
105 TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleElements) {
106   for (int i = 1; i < 5; ++i)
107     PostExecuteTask(i);
108   RunLoop().RunUntilIdle();
109   EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
110
111   StartRunner();
112   for (int i = 5; i < 9; ++i)
113     PostExecuteTask(i);
114   RunLoop().RunUntilIdle();
115   EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
116 }
117
118 TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleThreads) {
119   {
120     Thread thread1("DeferredSequencedTaskRunnerTestThread1");
121     Thread thread2("DeferredSequencedTaskRunnerTestThread2");
122     thread1.Start();
123     thread2.Start();
124     for (int i = 0; i < 5; ++i) {
125       thread1.task_runner()->PostTask(
126           FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
127                               Unretained(this), 2 * i));
128       thread2.task_runner()->PostTask(
129           FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
130                               Unretained(this), 2 * i + 1));
131       if (i == 2) {
132         thread1.task_runner()->PostTask(
133             FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::StartRunner,
134                                 Unretained(this)));
135       }
136     }
137   }
138
139   RunLoop().RunUntilIdle();
140   EXPECT_THAT(executed_task_ids_,
141       testing::WhenSorted(testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)));
142 }
143
144 TEST_F(DeferredSequencedTaskRunnerTest, ObjectDestructionOrder) {
145   {
146     Thread thread("DeferredSequencedTaskRunnerTestThread");
147     thread.Start();
148     runner_ = new DeferredSequencedTaskRunner(thread.task_runner());
149     for (int i = 0; i < 5; ++i) {
150       {
151         // Use a block to ensure that no reference to |short_lived_object|
152         // is kept on the main thread after it is posted to |runner_|.
153         scoped_refptr<ExecuteTaskOnDestructor> short_lived_object =
154             new ExecuteTaskOnDestructor(this, 2 * i);
155         runner_->PostTask(
156             FROM_HERE,
157             BindOnce(&DeferredSequencedTaskRunnerTest::DoNothing,
158                      Unretained(this), RetainedRef(short_lived_object)));
159       }
160       // |short_lived_object| with id |2 * i| should be destroyed before the
161       // task |2 * i + 1| is executed.
162       PostExecuteTask(2 * i + 1);
163     }
164     StartRunner();
165   }
166
167   // All |short_lived_object| with id |2 * i| are destroyed before the task
168   // |2 * i + 1| is executed.
169   EXPECT_THAT(executed_task_ids_,
170               testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
171 }
172
173 void GetRunsTasksInCurrentSequence(bool* result,
174                                    scoped_refptr<SequencedTaskRunner> runner,
175                                    OnceClosure quit) {
176   *result = runner->RunsTasksInCurrentSequence();
177   std::move(quit).Run();
178 }
179
180 TEST_F(DeferredSequencedTaskRunnerTest, RunsTasksInCurrentSequence) {
181   scoped_refptr<DeferredSequencedTaskRunner> runner =
182       MakeRefCounted<DeferredSequencedTaskRunner>();
183   EXPECT_TRUE(runner->RunsTasksInCurrentSequence());
184
185   Thread thread1("DeferredSequencedTaskRunnerTestThread1");
186   thread1.Start();
187   bool runs_task_in_current_thread = true;
188   base::RunLoop run_loop;
189   thread1.task_runner()->PostTask(
190       FROM_HERE,
191       BindOnce(&GetRunsTasksInCurrentSequence, &runs_task_in_current_thread,
192                runner, run_loop.QuitClosure()));
193   run_loop.Run();
194   EXPECT_FALSE(runs_task_in_current_thread);
195 }
196
197 TEST_F(DeferredSequencedTaskRunnerTest, StartWithTaskRunner) {
198   scoped_refptr<DeferredSequencedTaskRunner> runner =
199       MakeRefCounted<DeferredSequencedTaskRunner>();
200   bool run_called = false;
201   base::RunLoop run_loop;
202   runner->PostTask(FROM_HERE,
203                    BindOnce(
204                        [](bool* run_called, base::OnceClosure quit_closure) {
205                          *run_called = true;
206                          std::move(quit_closure).Run();
207                        },
208                        &run_called, run_loop.QuitClosure()));
209   runner->StartWithTaskRunner(ThreadTaskRunnerHandle::Get());
210   run_loop.Run();
211   EXPECT_TRUE(run_called);
212 }
213
214 }  // namespace
215 }  // namespace base