blob: 27e6fc399393407ca159efcae4b03f8eac142851 [file] [log] [blame]
[email protected]44106182012-04-06 03:53:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]1c4947f2009-01-15 22:25:112// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f7b98b32013-02-05 08:14:155#include "base/synchronization/waitable_event_watcher.h"
6
[email protected]329be052013-02-04 18:14:287#include "base/bind.h"
8#include "base/callback.h"
avi9b6f42932015-12-26 22:15:149#include "base/macros.h"
atuchin54d83152017-05-10 06:30:0110#include "base/memory/ptr_util.h"
[email protected]f7b98b32013-02-05 08:14:1511#include "base/run_loop.h"
[email protected]44f9c952011-01-02 06:05:3912#include "base/synchronization/waitable_event.h"
Gabriel Charettec7108742019-08-23 03:31:4013#include "base/test/task_environment.h"
[email protected]ce072a72010-12-31 20:02:1614#include "base/threading/platform_thread.h"
atuchin54d83152017-05-10 06:30:0115#include "base/threading/sequenced_task_runner_handle.h"
Sami Kyostila3f49cb572018-11-19 13:01:0916#include "base/threading/thread_task_runner_handle.h"
avi9b6f42932015-12-26 22:15:1417#include "build/build_config.h"
[email protected]1c4947f2009-01-15 22:25:1118#include "testing/gtest/include/gtest/gtest.h"
19
[email protected]44f9c952011-01-02 06:05:3920namespace base {
[email protected]1c4947f2009-01-15 22:25:1121
22namespace {
23
Sami Kyostila3f49cb572018-11-19 13:01:0924// The main thread types on which each waitable event should be tested.
Gabriel Charette694c3c332019-08-19 14:53:0525const test::TaskEnvironment::MainThreadType testing_main_threads[] = {
26 test::TaskEnvironment::MainThreadType::DEFAULT,
27 test::TaskEnvironment::MainThreadType::IO,
[email protected]840246b2012-07-18 08:06:5028#if !defined(OS_IOS) // iOS does not allow direct running of the UI loop.
Gabriel Charette694c3c332019-08-19 14:53:0529 test::TaskEnvironment::MainThreadType::UI,
[email protected]840246b2012-07-18 08:06:5030#endif
31};
32
[email protected]329be052013-02-04 18:14:2833void QuitWhenSignaled(WaitableEvent* event) {
Gabriel Charette53a9ef812017-07-26 12:36:2334 RunLoop::QuitCurrentWhenIdleDeprecated();
[email protected]329be052013-02-04 18:14:2835}
[email protected]1eaa54792013-01-31 23:14:2736
[email protected]329be052013-02-04 18:14:2837class DecrementCountContainer {
[email protected]1eaa54792013-01-31 23:14:2738 public:
Robert Sesekb44f8962017-06-30 21:21:1339 explicit DecrementCountContainer(int* counter) : counter_(counter) {}
[email protected]329be052013-02-04 18:14:2840 void OnWaitableEventSignaled(WaitableEvent* object) {
atuchin54d83152017-05-10 06:30:0141 // NOTE: |object| may be already deleted.
[email protected]1c4947f2009-01-15 22:25:1142 --(*counter_);
43 }
Robert Sesekb44f8962017-06-30 21:21:1344
[email protected]1c4947f2009-01-15 22:25:1145 private:
46 int* counter_;
47};
48
Robert Sesek3b3333772017-06-30 18:21:5649} // namespace
50
51class WaitableEventWatcherTest
Gabriel Charette694c3c332019-08-19 14:53:0552 : public testing::TestWithParam<test::TaskEnvironment::MainThreadType> {};
Robert Sesek3b3333772017-06-30 18:21:5653
Robert Sesekcfab3ad2017-08-01 16:25:4354TEST_P(WaitableEventWatcherTest, BasicSignalManual) {
Gabriel Charette694c3c332019-08-19 14:53:0555 test::TaskEnvironment task_environment(GetParam());
[email protected]1c4947f2009-01-15 22:25:1156
57 // A manual-reset event that is not yet signaled.
gab75d72332016-06-01 21:15:3358 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
59 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]1c4947f2009-01-15 22:25:1160
61 WaitableEventWatcher watcher;
Hajime Hoshi138652c92018-01-12 15:11:4462 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
63 SequencedTaskRunnerHandle::Get());
[email protected]1c4947f2009-01-15 22:25:1164
65 event.Signal();
66
fdoray10224582016-06-30 18:17:3967 RunLoop().Run();
Robert Sesekcfab3ad2017-08-01 16:25:4368
69 EXPECT_TRUE(event.IsSignaled());
70}
71
72TEST_P(WaitableEventWatcherTest, BasicSignalAutomatic) {
Gabriel Charette694c3c332019-08-19 14:53:0573 test::TaskEnvironment task_environment(GetParam());
Robert Sesekcfab3ad2017-08-01 16:25:4374
75 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
76 WaitableEvent::InitialState::NOT_SIGNALED);
77
78 WaitableEventWatcher watcher;
Hajime Hoshi138652c92018-01-12 15:11:4479 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
80 SequencedTaskRunnerHandle::Get());
Robert Sesekcfab3ad2017-08-01 16:25:4381
82 event.Signal();
83
84 RunLoop().Run();
85
86 // The WaitableEventWatcher consumes the event signal.
87 EXPECT_FALSE(event.IsSignaled());
[email protected]1c4947f2009-01-15 22:25:1188}
89
Robert Sesek3b3333772017-06-30 18:21:5690TEST_P(WaitableEventWatcherTest, BasicCancel) {
Gabriel Charette694c3c332019-08-19 14:53:0591 test::TaskEnvironment task_environment(GetParam());
[email protected]1c4947f2009-01-15 22:25:1192
93 // A manual-reset event that is not yet signaled.
gab75d72332016-06-01 21:15:3394 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
95 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]1c4947f2009-01-15 22:25:1196
97 WaitableEventWatcher watcher;
98
Hajime Hoshi138652c92018-01-12 15:11:4499 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
100 SequencedTaskRunnerHandle::Get());
[email protected]1c4947f2009-01-15 22:25:11101
102 watcher.StopWatching();
103}
104
Robert Sesek3b3333772017-06-30 18:21:56105TEST_P(WaitableEventWatcherTest, CancelAfterSet) {
Gabriel Charette694c3c332019-08-19 14:53:05106 test::TaskEnvironment task_environment(GetParam());
[email protected]1c4947f2009-01-15 22:25:11107
108 // A manual-reset event that is not yet signaled.
gab75d72332016-06-01 21:15:33109 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
110 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]1c4947f2009-01-15 22:25:11111
112 WaitableEventWatcher watcher;
113
114 int counter = 1;
[email protected]329be052013-02-04 18:14:28115 DecrementCountContainer delegate(&counter);
tzik130cfd0c2017-04-18 03:49:05116 WaitableEventWatcher::EventCallback callback = BindOnce(
117 &DecrementCountContainer::OnWaitableEventSignaled, Unretained(&delegate));
Hajime Hoshi138652c92018-01-12 15:11:44118 watcher.StartWatching(&event, std::move(callback),
119 SequencedTaskRunnerHandle::Get());
[email protected]1c4947f2009-01-15 22:25:11120
121 event.Signal();
122
123 // Let the background thread do its business
Hajime Hoshi138652c92018-01-12 15:11:44124 PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
[email protected]1c4947f2009-01-15 22:25:11125
126 watcher.StopWatching();
127
[email protected]f7b98b32013-02-05 08:14:15128 RunLoop().RunUntilIdle();
[email protected]1c4947f2009-01-15 22:25:11129
130 // Our delegate should not have fired.
131 EXPECT_EQ(1, counter);
132}
133
Sami Kyostila3f49cb572018-11-19 13:01:09134TEST_P(WaitableEventWatcherTest, OutlivesTaskEnvironment) {
135 // Simulate a task environment that dies before an WaitableEventWatcher. This
[email protected]1c4947f2009-01-15 22:25:11136 // ordinarily doesn't happen when people use the Thread class, but it can
137 // happen when people use the Singleton pattern or atexit.
gab75d72332016-06-01 21:15:33138 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
139 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]1c4947f2009-01-15 22:25:11140 {
Hajime Hoshi138652c92018-01-12 15:11:44141 std::unique_ptr<WaitableEventWatcher> watcher;
[email protected]1c4947f2009-01-15 22:25:11142 {
Gabriel Charette694c3c332019-08-19 14:53:05143 test::TaskEnvironment task_environment(GetParam());
Hajime Hoshi138652c92018-01-12 15:11:44144 watcher = std::make_unique<WaitableEventWatcher>();
[email protected]1c4947f2009-01-15 22:25:11145
Hajime Hoshi138652c92018-01-12 15:11:44146 watcher->StartWatching(&event, BindOnce(&QuitWhenSignaled),
147 SequencedTaskRunnerHandle::Get());
[email protected]1c4947f2009-01-15 22:25:11148 }
149 }
150}
151
Robert Sesekcfab3ad2017-08-01 16:25:43152TEST_P(WaitableEventWatcherTest, SignaledAtStartManual) {
Gabriel Charette694c3c332019-08-19 14:53:05153 test::TaskEnvironment task_environment(GetParam());
Robert Sesekb44f8962017-06-30 21:21:13154
155 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
156 WaitableEvent::InitialState::SIGNALED);
157
158 WaitableEventWatcher watcher;
Hajime Hoshi138652c92018-01-12 15:11:44159 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
160 SequencedTaskRunnerHandle::Get());
Robert Sesekb44f8962017-06-30 21:21:13161
162 RunLoop().Run();
Robert Sesekcfab3ad2017-08-01 16:25:43163
164 EXPECT_TRUE(event.IsSignaled());
165}
166
167TEST_P(WaitableEventWatcherTest, SignaledAtStartAutomatic) {
Gabriel Charette694c3c332019-08-19 14:53:05168 test::TaskEnvironment task_environment(GetParam());
Robert Sesekcfab3ad2017-08-01 16:25:43169
170 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
171 WaitableEvent::InitialState::SIGNALED);
172
173 WaitableEventWatcher watcher;
Hajime Hoshi138652c92018-01-12 15:11:44174 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
175 SequencedTaskRunnerHandle::Get());
Robert Sesekcfab3ad2017-08-01 16:25:43176
177 RunLoop().Run();
178
179 // The watcher consumes the event signal.
180 EXPECT_FALSE(event.IsSignaled());
Robert Sesekb44f8962017-06-30 21:21:13181}
182
183TEST_P(WaitableEventWatcherTest, StartWatchingInCallback) {
Gabriel Charette694c3c332019-08-19 14:53:05184 test::TaskEnvironment task_environment(GetParam());
Robert Sesekb44f8962017-06-30 21:21:13185
186 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
187 WaitableEvent::InitialState::NOT_SIGNALED);
188
189 WaitableEventWatcher watcher;
190 watcher.StartWatching(
Hajime Hoshi138652c92018-01-12 15:11:44191 &event,
192 BindOnce(
193 [](WaitableEventWatcher* watcher, WaitableEvent* event) {
194 // |event| is manual, so the second watcher will run
195 // immediately.
196 watcher->StartWatching(event, BindOnce(&QuitWhenSignaled),
197 SequencedTaskRunnerHandle::Get());
198 },
199 &watcher),
200 SequencedTaskRunnerHandle::Get());
Robert Sesekb44f8962017-06-30 21:21:13201
202 event.Signal();
203
204 RunLoop().Run();
205}
206
Greg Thompson96a39102021-03-16 10:11:08207// Disabled due to flakes; see https://crbug.com/1188547.
208TEST_P(WaitableEventWatcherTest, DISABLED_MultipleWatchersManual) {
Gabriel Charette694c3c332019-08-19 14:53:05209 test::TaskEnvironment task_environment(GetParam());
Robert Sesekcfab3ad2017-08-01 16:25:43210
211 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
212 WaitableEvent::InitialState::NOT_SIGNALED);
213
214 int counter1 = 0;
215 int counter2 = 0;
216
217 auto callback = [](RunLoop* run_loop, int* counter, WaitableEvent* event) {
218 ++(*counter);
219 run_loop->QuitWhenIdle();
220 };
221
222 RunLoop run_loop;
223
224 WaitableEventWatcher watcher1;
225 watcher1.StartWatching(
Hajime Hoshi138652c92018-01-12 15:11:44226 &event, BindOnce(callback, Unretained(&run_loop), Unretained(&counter1)),
227 SequencedTaskRunnerHandle::Get());
Robert Sesekcfab3ad2017-08-01 16:25:43228
229 WaitableEventWatcher watcher2;
230 watcher2.StartWatching(
Hajime Hoshi138652c92018-01-12 15:11:44231 &event, BindOnce(callback, Unretained(&run_loop), Unretained(&counter2)),
232 SequencedTaskRunnerHandle::Get());
Robert Sesekcfab3ad2017-08-01 16:25:43233
234 event.Signal();
235 run_loop.Run();
236
237 EXPECT_EQ(1, counter1);
238 EXPECT_EQ(1, counter2);
239 EXPECT_TRUE(event.IsSignaled());
240}
241
242// Tests that only one async waiter gets called back for an auto-reset event.
243TEST_P(WaitableEventWatcherTest, MultipleWatchersAutomatic) {
Gabriel Charette694c3c332019-08-19 14:53:05244 test::TaskEnvironment task_environment(GetParam());
Robert Sesekcfab3ad2017-08-01 16:25:43245
246 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
247 WaitableEvent::InitialState::NOT_SIGNALED);
248
249 int counter1 = 0;
250 int counter2 = 0;
251
252 auto callback = [](RunLoop** run_loop, int* counter, WaitableEvent* event) {
253 ++(*counter);
254 (*run_loop)->QuitWhenIdle();
255 };
256
257 // The same RunLoop instance cannot be Run more than once, and it is
258 // undefined which watcher will get called back first. Have the callback
259 // dereference this pointer to quit the loop, which will be updated on each
260 // Run.
261 RunLoop* current_run_loop;
262
263 WaitableEventWatcher watcher1;
264 watcher1.StartWatching(
265 &event,
Hajime Hoshi138652c92018-01-12 15:11:44266 BindOnce(callback, Unretained(&current_run_loop), Unretained(&counter1)),
267 SequencedTaskRunnerHandle::Get());
Robert Sesekcfab3ad2017-08-01 16:25:43268
269 WaitableEventWatcher watcher2;
270 watcher2.StartWatching(
271 &event,
Hajime Hoshi138652c92018-01-12 15:11:44272 BindOnce(callback, Unretained(&current_run_loop), Unretained(&counter2)),
273 SequencedTaskRunnerHandle::Get());
Robert Sesekcfab3ad2017-08-01 16:25:43274
275 event.Signal();
276 {
277 RunLoop run_loop;
278 current_run_loop = &run_loop;
279 run_loop.Run();
280 }
281
282 // Only one of the waiters should have been signaled.
283 EXPECT_TRUE((counter1 == 1) ^ (counter2 == 1));
284
285 EXPECT_FALSE(event.IsSignaled());
286
287 event.Signal();
288 {
289 RunLoop run_loop;
290 current_run_loop = &run_loop;
291 run_loop.Run();
292 }
293
294 EXPECT_FALSE(event.IsSignaled());
295
296 // The other watcher should have been signaled.
297 EXPECT_EQ(1, counter1);
298 EXPECT_EQ(1, counter2);
299}
300
Robert Sesek3b3333772017-06-30 18:21:56301// To help detect errors around deleting WaitableEventWatcher, an additional
302// bool parameter is used to test sleeping between watching and deletion.
303class WaitableEventWatcherDeletionTest
Sami Kyostila3f49cb572018-11-19 13:01:09304 : public testing::TestWithParam<
Gabriel Charette694c3c332019-08-19 14:53:05305 std::tuple<test::TaskEnvironment::MainThreadType, bool>> {};
Robert Sesek3b3333772017-06-30 18:21:56306
307TEST_P(WaitableEventWatcherDeletionTest, DeleteUnder) {
Gabriel Charette694c3c332019-08-19 14:53:05308 test::TaskEnvironment::MainThreadType main_thread_type;
Robert Sesek3b3333772017-06-30 18:21:56309 bool delay_after_delete;
Sami Kyostila3f49cb572018-11-19 13:01:09310 std::tie(main_thread_type, delay_after_delete) = GetParam();
Robert Sesek3b3333772017-06-30 18:21:56311
[email protected]c891ab92009-03-26 18:28:19312 // Delete the WaitableEvent out from under the Watcher. This is explictly
313 // allowed by the interface.
314
Gabriel Charette694c3c332019-08-19 14:53:05315 test::TaskEnvironment task_environment(main_thread_type);
[email protected]c891ab92009-03-26 18:28:19316
317 {
318 WaitableEventWatcher watcher;
319
atuchin54d83152017-05-10 06:30:01320 auto* event = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
321 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]329be052013-02-04 18:14:28322
Hajime Hoshi138652c92018-01-12 15:11:44323 watcher.StartWatching(event, BindOnce(&QuitWhenSignaled),
324 SequencedTaskRunnerHandle::Get());
atuchin54d83152017-05-10 06:30:01325
326 if (delay_after_delete) {
327 // On Windows that sleep() improves the chance to catch some problems.
328 // It postpones the dtor |watcher| (which immediately cancel the waiting)
329 // and gives some time to run to a created background thread.
330 // Unfortunately, that thread is under OS control and we can't
331 // manipulate it directly.
Hajime Hoshi138652c92018-01-12 15:11:44332 PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
atuchin54d83152017-05-10 06:30:01333 }
334
[email protected]c891ab92009-03-26 18:28:19335 delete event;
336 }
337}
338
Robert Sesek3b3333772017-06-30 18:21:56339TEST_P(WaitableEventWatcherDeletionTest, SignalAndDelete) {
Gabriel Charette694c3c332019-08-19 14:53:05340 test::TaskEnvironment::MainThreadType main_thread_type;
Robert Sesek3b3333772017-06-30 18:21:56341 bool delay_after_delete;
Sami Kyostila3f49cb572018-11-19 13:01:09342 std::tie(main_thread_type, delay_after_delete) = GetParam();
Robert Sesek3b3333772017-06-30 18:21:56343
atuchin54d83152017-05-10 06:30:01344 // Signal and immediately delete the WaitableEvent out from under the Watcher.
345
Gabriel Charette694c3c332019-08-19 14:53:05346 test::TaskEnvironment task_environment(main_thread_type);
atuchin54d83152017-05-10 06:30:01347
348 {
349 WaitableEventWatcher watcher;
350
Jeremy Roman9532f252017-08-16 23:27:24351 auto event = std::make_unique<WaitableEvent>(
atuchin54d83152017-05-10 06:30:01352 WaitableEvent::ResetPolicy::AUTOMATIC,
353 WaitableEvent::InitialState::NOT_SIGNALED);
354
Hajime Hoshi138652c92018-01-12 15:11:44355 watcher.StartWatching(event.get(), BindOnce(&QuitWhenSignaled),
356 SequencedTaskRunnerHandle::Get());
atuchin54d83152017-05-10 06:30:01357 event->Signal();
358 event.reset();
359
360 if (delay_after_delete) {
361 // On Windows that sleep() improves the chance to catch some problems.
362 // It postpones the dtor |watcher| (which immediately cancel the waiting)
363 // and gives some time to run to a created background thread.
364 // Unfortunately, that thread is under OS control and we can't
365 // manipulate it directly.
Hajime Hoshi138652c92018-01-12 15:11:44366 PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
atuchin54d83152017-05-10 06:30:01367 }
368
369 // Wait for the watcher callback.
370 RunLoop().Run();
371 }
372}
373
Robert Sesek6d38e782017-07-13 00:46:50374// Tests deleting the WaitableEventWatcher between signaling the event and
375// when the callback should be run.
376TEST_P(WaitableEventWatcherDeletionTest, DeleteWatcherBeforeCallback) {
Gabriel Charette694c3c332019-08-19 14:53:05377 test::TaskEnvironment::MainThreadType main_thread_type;
Robert Sesek6d38e782017-07-13 00:46:50378 bool delay_after_delete;
Sami Kyostila3f49cb572018-11-19 13:01:09379 std::tie(main_thread_type, delay_after_delete) = GetParam();
Robert Sesek6d38e782017-07-13 00:46:50380
Gabriel Charette694c3c332019-08-19 14:53:05381 test::TaskEnvironment task_environment(main_thread_type);
Robert Sesek6d38e782017-07-13 00:46:50382 scoped_refptr<SingleThreadTaskRunner> task_runner =
Sami Kyostila3f49cb572018-11-19 13:01:09383 ThreadTaskRunnerHandle::Get();
Robert Sesek6d38e782017-07-13 00:46:50384
385 // Flag used to esnure that the |watcher_callback| never runs.
386 bool did_callback = false;
387
388 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
389 WaitableEvent::InitialState::NOT_SIGNALED);
Jeremy Roman9532f252017-08-16 23:27:24390 auto watcher = std::make_unique<WaitableEventWatcher>();
Robert Sesek6d38e782017-07-13 00:46:50391
392 // Queue up a series of tasks:
393 // 1. StartWatching the WaitableEvent
394 // 2. Signal the event (which will result in another task getting posted to
395 // the |task_runner|)
396 // 3. Delete the WaitableEventWatcher
397 // 4. WaitableEventWatcher callback should run (from #2)
398
399 WaitableEventWatcher::EventCallback watcher_callback = BindOnce(
400 [](bool* did_callback, WaitableEvent*) {
401 *did_callback = true;
402 },
403 Unretained(&did_callback));
404
405 task_runner->PostTask(
406 FROM_HERE, BindOnce(IgnoreResult(&WaitableEventWatcher::StartWatching),
407 Unretained(watcher.get()), Unretained(&event),
Hajime Hoshi138652c92018-01-12 15:11:44408 std::move(watcher_callback), task_runner));
Robert Sesek6d38e782017-07-13 00:46:50409 task_runner->PostTask(FROM_HERE,
410 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
411 task_runner->DeleteSoon(FROM_HERE, std::move(watcher));
412 if (delay_after_delete) {
413 task_runner->PostTask(FROM_HERE, BindOnce(&PlatformThread::Sleep,
414 TimeDelta::FromMilliseconds(30)));
415 }
416
417 RunLoop().RunUntilIdle();
418
419 EXPECT_FALSE(did_callback);
420}
421
Ilia Samsonova2885f72019-11-20 22:16:58422INSTANTIATE_TEST_SUITE_P(All,
Victor Costan033b9ac2019-01-29 00:52:16423 WaitableEventWatcherTest,
424 testing::ValuesIn(testing_main_threads));
[email protected]b57d33c52009-01-15 22:58:53425
Victor Costan033b9ac2019-01-29 00:52:16426INSTANTIATE_TEST_SUITE_P(
Ilia Samsonova2885f72019-11-20 22:16:58427 All,
Robert Sesek3b3333772017-06-30 18:21:56428 WaitableEventWatcherDeletionTest,
Sami Kyostila3f49cb572018-11-19 13:01:09429 testing::Combine(testing::ValuesIn(testing_main_threads), testing::Bool()));
[email protected]44f9c952011-01-02 06:05:39430
431} // namespace base