1 // Copyright (c) 2012 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/observer_list.h"
6 #include "base/observer_list_threadsafe.h"
7
8 #include <memory>
9 #include <utility>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/compiler_specific.h"
14 #include "base/location.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/run_loop.h"
18 #include "base/sequenced_task_runner.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/strings/string_piece.h"
21 #include "base/synchronization/waitable_event.h"
22 // TaskScheduler not supported in libchrome
23 // #include "base/task_scheduler/post_task.h"
24 // #include "base/task_scheduler/task_scheduler.h"
25 #include "base/test/gtest_util.h"
26 #include "base/test/scoped_task_environment.h"
27 #include "base/threading/platform_thread.h"
28 #include "base/threading/thread_restrictions.h"
29 #include "build/build_config.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 namespace base {
34 namespace {
35
36 class Foo {
37 public:
38 virtual void Observe(int x) = 0;
39 virtual ~Foo() = default;
GetValue() const40 virtual int GetValue() const { return 0; }
41 };
42
43 class Adder : public Foo {
44 public:
Adder(int scaler)45 explicit Adder(int scaler) : total(0), scaler_(scaler) {}
46 ~Adder() override = default;
47
Observe(int x)48 void Observe(int x) override { total += x * scaler_; }
GetValue() const49 int GetValue() const override { return total; }
50
51 int total;
52
53 private:
54 int scaler_;
55 };
56
57 class Disrupter : public Foo {
58 public:
Disrupter(ObserverList<Foo> * list,Foo * doomed,bool remove_self)59 Disrupter(ObserverList<Foo>* list, Foo* doomed, bool remove_self)
60 : list_(list), doomed_(doomed), remove_self_(remove_self) {}
Disrupter(ObserverList<Foo> * list,Foo * doomed)61 Disrupter(ObserverList<Foo>* list, Foo* doomed)
62 : Disrupter(list, doomed, false) {}
Disrupter(ObserverList<Foo> * list,bool remove_self)63 Disrupter(ObserverList<Foo>* list, bool remove_self)
64 : Disrupter(list, nullptr, remove_self) {}
65
66 ~Disrupter() override = default;
67
Observe(int x)68 void Observe(int x) override {
69 if (remove_self_)
70 list_->RemoveObserver(this);
71 if (doomed_)
72 list_->RemoveObserver(doomed_);
73 }
74
SetDoomed(Foo * doomed)75 void SetDoomed(Foo* doomed) { doomed_ = doomed; }
76
77 private:
78 ObserverList<Foo>* list_;
79 Foo* doomed_;
80 bool remove_self_;
81 };
82
83 template <typename ObserverListType>
84 class AddInObserve : public Foo {
85 public:
AddInObserve(ObserverListType * observer_list)86 explicit AddInObserve(ObserverListType* observer_list)
87 : observer_list(observer_list), to_add_() {}
88
SetToAdd(Foo * to_add)89 void SetToAdd(Foo* to_add) { to_add_ = to_add; }
90
Observe(int x)91 void Observe(int x) override {
92 if (to_add_) {
93 observer_list->AddObserver(to_add_);
94 to_add_ = nullptr;
95 }
96 }
97
98 ObserverListType* observer_list;
99 Foo* to_add_;
100 };
101
102
103 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test.
104
105 // A thread for use in the ThreadSafeObserver test
106 // which will add and remove itself from the notification
107 // list repeatedly.
108 class AddRemoveThread : public PlatformThread::Delegate,
109 public Foo {
110 public:
AddRemoveThread(ObserverListThreadSafe<Foo> * list,bool notify,WaitableEvent * ready)111 AddRemoveThread(ObserverListThreadSafe<Foo>* list,
112 bool notify,
113 WaitableEvent* ready)
114 : list_(list),
115 loop_(nullptr),
116 in_list_(false),
117 start_(Time::Now()),
118 count_observes_(0),
119 count_addtask_(0),
120 do_notifies_(notify),
121 ready_(ready),
122 weak_factory_(this) {}
123
124 ~AddRemoveThread() override = default;
125
ThreadMain()126 void ThreadMain() override {
127 loop_ = new MessageLoop(); // Fire up a message loop.
128 loop_->task_runner()->PostTask(
129 FROM_HERE,
130 base::BindOnce(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
131 ready_->Signal();
132 // After ready_ is signaled, loop_ is only accessed by the main test thread
133 // (i.e. not this thread) in particular by Quit() which causes Run() to
134 // return, and we "control" loop_ again.
135 RunLoop run_loop;
136 quit_loop_ = run_loop.QuitClosure();
137 run_loop.Run();
138 delete loop_;
139 loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
140 delete this;
141 }
142
143 // This task just keeps posting to itself in an attempt
144 // to race with the notifier.
AddTask()145 void AddTask() {
146 count_addtask_++;
147
148 if ((Time::Now() - start_).InMilliseconds() > kThreadRunTime) {
149 VLOG(1) << "DONE!";
150 return;
151 }
152
153 if (!in_list_) {
154 list_->AddObserver(this);
155 in_list_ = true;
156 }
157
158 if (do_notifies_) {
159 list_->Notify(FROM_HERE, &Foo::Observe, 10);
160 }
161
162 loop_->task_runner()->PostTask(
163 FROM_HERE,
164 base::BindOnce(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
165 }
166
167 // This function is only callable from the main thread.
Quit()168 void Quit() { std::move(quit_loop_).Run(); }
169
Observe(int x)170 void Observe(int x) override {
171 count_observes_++;
172
173 // If we're getting called after we removed ourselves from
174 // the list, that is very bad!
175 DCHECK(in_list_);
176
177 // This callback should fire on the appropriate thread
178 EXPECT_EQ(loop_, MessageLoop::current());
179
180 list_->RemoveObserver(this);
181 in_list_ = false;
182 }
183
184 private:
185 ObserverListThreadSafe<Foo>* list_;
186 MessageLoop* loop_;
187 bool in_list_; // Are we currently registered for notifications.
188 // in_list_ is only used on |this| thread.
189 Time start_; // The time we started the test.
190
191 int count_observes_; // Number of times we observed.
192 int count_addtask_; // Number of times thread AddTask was called
193 bool do_notifies_; // Whether these threads should do notifications.
194 WaitableEvent* ready_;
195
196 base::OnceClosure quit_loop_;
197
198 base::WeakPtrFactory<AddRemoveThread> weak_factory_;
199 };
200
201 } // namespace
202
TEST(ObserverListTest,BasicTest)203 TEST(ObserverListTest, BasicTest) {
204 ObserverList<Foo> observer_list;
205 const ObserverList<Foo>& const_observer_list = observer_list;
206
207 {
208 const ObserverList<Foo>::const_iterator it1 = const_observer_list.begin();
209 EXPECT_EQ(it1, const_observer_list.end());
210 // Iterator copy.
211 const ObserverList<Foo>::const_iterator it2 = it1;
212 EXPECT_EQ(it2, it1);
213 // Iterator assignment.
214 ObserverList<Foo>::const_iterator it3;
215 it3 = it2;
216 EXPECT_EQ(it3, it1);
217 EXPECT_EQ(it3, it2);
218 // Self assignment.
219 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
220 EXPECT_EQ(it3, it1);
221 EXPECT_EQ(it3, it2);
222 }
223
224 {
225 const ObserverList<Foo>::iterator it1 = observer_list.begin();
226 EXPECT_EQ(it1, observer_list.end());
227 // Iterator copy.
228 const ObserverList<Foo>::iterator it2 = it1;
229 EXPECT_EQ(it2, it1);
230 // Iterator assignment.
231 ObserverList<Foo>::iterator it3;
232 it3 = it2;
233 EXPECT_EQ(it3, it1);
234 EXPECT_EQ(it3, it2);
235 // Self assignment.
236 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
237 EXPECT_EQ(it3, it1);
238 EXPECT_EQ(it3, it2);
239 }
240
241 Adder a(1), b(-1), c(1), d(-1), e(-1);
242 Disrupter evil(&observer_list, &c);
243
244 observer_list.AddObserver(&a);
245 observer_list.AddObserver(&b);
246
247 EXPECT_TRUE(const_observer_list.HasObserver(&a));
248 EXPECT_FALSE(const_observer_list.HasObserver(&c));
249
250 {
251 const ObserverList<Foo>::const_iterator it1 = const_observer_list.begin();
252 EXPECT_NE(it1, const_observer_list.end());
253 // Iterator copy.
254 const ObserverList<Foo>::const_iterator it2 = it1;
255 EXPECT_EQ(it2, it1);
256 EXPECT_NE(it2, const_observer_list.end());
257 // Iterator assignment.
258 ObserverList<Foo>::const_iterator it3;
259 it3 = it2;
260 EXPECT_EQ(it3, it1);
261 EXPECT_EQ(it3, it2);
262 // Self assignment.
263 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
264 EXPECT_EQ(it3, it1);
265 EXPECT_EQ(it3, it2);
266 // Iterator post increment.
267 ObserverList<Foo>::const_iterator it4 = it3++;
268 EXPECT_EQ(it4, it1);
269 EXPECT_EQ(it4, it2);
270 EXPECT_NE(it4, it3);
271 }
272
273 {
274 const ObserverList<Foo>::iterator it1 = observer_list.begin();
275 EXPECT_NE(it1, observer_list.end());
276 // Iterator copy.
277 const ObserverList<Foo>::iterator it2 = it1;
278 EXPECT_EQ(it2, it1);
279 EXPECT_NE(it2, observer_list.end());
280 // Iterator assignment.
281 ObserverList<Foo>::iterator it3;
282 it3 = it2;
283 EXPECT_EQ(it3, it1);
284 EXPECT_EQ(it3, it2);
285 // Self assignment.
286 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
287 EXPECT_EQ(it3, it1);
288 EXPECT_EQ(it3, it2);
289 // Iterator post increment.
290 ObserverList<Foo>::iterator it4 = it3++;
291 EXPECT_EQ(it4, it1);
292 EXPECT_EQ(it4, it2);
293 EXPECT_NE(it4, it3);
294 }
295
296 for (auto& observer : observer_list)
297 observer.Observe(10);
298
299 observer_list.AddObserver(&evil);
300 observer_list.AddObserver(&c);
301 observer_list.AddObserver(&d);
302
303 // Removing an observer not in the list should do nothing.
304 observer_list.RemoveObserver(&e);
305
306 for (auto& observer : observer_list)
307 observer.Observe(10);
308
309 EXPECT_EQ(20, a.total);
310 EXPECT_EQ(-20, b.total);
311 EXPECT_EQ(0, c.total);
312 EXPECT_EQ(-10, d.total);
313 EXPECT_EQ(0, e.total);
314 }
315
TEST(ObserverListTest,CompactsWhenNoActiveIterator)316 TEST(ObserverListTest, CompactsWhenNoActiveIterator) {
317 ObserverList<const Foo> ol;
318 const ObserverList<const Foo>& col = ol;
319
320 const Adder a(1);
321 const Adder b(2);
322 const Adder c(3);
323
324 ol.AddObserver(&a);
325 ol.AddObserver(&b);
326
327 EXPECT_TRUE(col.HasObserver(&a));
328 EXPECT_FALSE(col.HasObserver(&c));
329
330 EXPECT_TRUE(col.might_have_observers());
331
332 using It = ObserverList<const Foo>::const_iterator;
333
334 {
335 It it = col.begin();
336 EXPECT_NE(it, col.end());
337 It ita = it;
338 EXPECT_EQ(ita, it);
339 EXPECT_NE(++it, col.end());
340 EXPECT_NE(ita, it);
341 It itb = it;
342 EXPECT_EQ(itb, it);
343 EXPECT_EQ(++it, col.end());
344
345 EXPECT_TRUE(col.might_have_observers());
346 EXPECT_EQ(&*ita, &a);
347 EXPECT_EQ(&*itb, &b);
348
349 ol.RemoveObserver(&a);
350 EXPECT_TRUE(col.might_have_observers());
351 EXPECT_FALSE(col.HasObserver(&a));
352 EXPECT_EQ(&*itb, &b);
353
354 ol.RemoveObserver(&b);
355 EXPECT_TRUE(col.might_have_observers());
356 EXPECT_FALSE(col.HasObserver(&a));
357 EXPECT_FALSE(col.HasObserver(&b));
358
359 it = It();
360 ita = It();
361 EXPECT_TRUE(col.might_have_observers());
362 ita = itb;
363 itb = It();
364 EXPECT_TRUE(col.might_have_observers());
365 ita = It();
366 EXPECT_FALSE(col.might_have_observers());
367 }
368
369 ol.AddObserver(&a);
370 ol.AddObserver(&b);
371 EXPECT_TRUE(col.might_have_observers());
372 ol.Clear();
373 EXPECT_FALSE(col.might_have_observers());
374
375 ol.AddObserver(&a);
376 ol.AddObserver(&b);
377 EXPECT_TRUE(col.might_have_observers());
378 {
379 const It it = col.begin();
380 ol.Clear();
381 EXPECT_TRUE(col.might_have_observers());
382 }
383 EXPECT_FALSE(col.might_have_observers());
384 }
385
TEST(ObserverListTest,DisruptSelf)386 TEST(ObserverListTest, DisruptSelf) {
387 ObserverList<Foo> observer_list;
388 Adder a(1), b(-1), c(1), d(-1);
389 Disrupter evil(&observer_list, true);
390
391 observer_list.AddObserver(&a);
392 observer_list.AddObserver(&b);
393
394 for (auto& observer : observer_list)
395 observer.Observe(10);
396
397 observer_list.AddObserver(&evil);
398 observer_list.AddObserver(&c);
399 observer_list.AddObserver(&d);
400
401 for (auto& observer : observer_list)
402 observer.Observe(10);
403
404 EXPECT_EQ(20, a.total);
405 EXPECT_EQ(-20, b.total);
406 EXPECT_EQ(10, c.total);
407 EXPECT_EQ(-10, d.total);
408 }
409
TEST(ObserverListTest,DisruptBefore)410 TEST(ObserverListTest, DisruptBefore) {
411 ObserverList<Foo> observer_list;
412 Adder a(1), b(-1), c(1), d(-1);
413 Disrupter evil(&observer_list, &b);
414
415 observer_list.AddObserver(&a);
416 observer_list.AddObserver(&b);
417 observer_list.AddObserver(&evil);
418 observer_list.AddObserver(&c);
419 observer_list.AddObserver(&d);
420
421 for (auto& observer : observer_list)
422 observer.Observe(10);
423 for (auto& observer : observer_list)
424 observer.Observe(10);
425
426 EXPECT_EQ(20, a.total);
427 EXPECT_EQ(-10, b.total);
428 EXPECT_EQ(20, c.total);
429 EXPECT_EQ(-20, d.total);
430 }
431
TEST(ObserverListThreadSafeTest,BasicTest)432 TEST(ObserverListThreadSafeTest, BasicTest) {
433 MessageLoop loop;
434
435 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
436 new ObserverListThreadSafe<Foo>);
437 Adder a(1);
438 Adder b(-1);
439 Adder c(1);
440 Adder d(-1);
441
442 observer_list->AddObserver(&a);
443 observer_list->AddObserver(&b);
444
445 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
446 RunLoop().RunUntilIdle();
447
448 observer_list->AddObserver(&c);
449 observer_list->AddObserver(&d);
450
451 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
452 observer_list->RemoveObserver(&c);
453 RunLoop().RunUntilIdle();
454
455 EXPECT_EQ(20, a.total);
456 EXPECT_EQ(-20, b.total);
457 EXPECT_EQ(0, c.total);
458 EXPECT_EQ(-10, d.total);
459 }
460
TEST(ObserverListThreadSafeTest,RemoveObserver)461 TEST(ObserverListThreadSafeTest, RemoveObserver) {
462 MessageLoop loop;
463
464 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
465 new ObserverListThreadSafe<Foo>);
466 Adder a(1), b(1);
467
468 // A workaround for the compiler bug. See http://crbug.com/121960.
469 EXPECT_NE(&a, &b);
470
471 // Should do nothing.
472 observer_list->RemoveObserver(&a);
473 observer_list->RemoveObserver(&b);
474
475 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
476 RunLoop().RunUntilIdle();
477
478 EXPECT_EQ(0, a.total);
479 EXPECT_EQ(0, b.total);
480
481 observer_list->AddObserver(&a);
482
483 // Should also do nothing.
484 observer_list->RemoveObserver(&b);
485
486 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
487 RunLoop().RunUntilIdle();
488
489 EXPECT_EQ(10, a.total);
490 EXPECT_EQ(0, b.total);
491 }
492
TEST(ObserverListThreadSafeTest,WithoutSequence)493 TEST(ObserverListThreadSafeTest, WithoutSequence) {
494 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
495 new ObserverListThreadSafe<Foo>);
496
497 Adder a(1), b(1), c(1);
498
499 // No sequence, so these should not be added.
500 observer_list->AddObserver(&a);
501 observer_list->AddObserver(&b);
502
503 {
504 // Add c when there's a sequence.
505 MessageLoop loop;
506 observer_list->AddObserver(&c);
507
508 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
509 RunLoop().RunUntilIdle();
510
511 EXPECT_EQ(0, a.total);
512 EXPECT_EQ(0, b.total);
513 EXPECT_EQ(10, c.total);
514
515 // Now add a when there's a sequence.
516 observer_list->AddObserver(&a);
517
518 // Remove c when there's a sequence.
519 observer_list->RemoveObserver(&c);
520
521 // Notify again.
522 observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
523 RunLoop().RunUntilIdle();
524
525 EXPECT_EQ(20, a.total);
526 EXPECT_EQ(0, b.total);
527 EXPECT_EQ(10, c.total);
528 }
529
530 // Removing should always succeed with or without a sequence.
531 observer_list->RemoveObserver(&a);
532
533 // Notifying should not fail but should also be a no-op.
534 MessageLoop loop;
535 observer_list->AddObserver(&b);
536 observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
537 RunLoop().RunUntilIdle();
538
539 EXPECT_EQ(20, a.total);
540 EXPECT_EQ(30, b.total);
541 EXPECT_EQ(10, c.total);
542 }
543
544 class FooRemover : public Foo {
545 public:
FooRemover(ObserverListThreadSafe<Foo> * list)546 explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {}
547 ~FooRemover() override = default;
548
AddFooToRemove(Foo * foo)549 void AddFooToRemove(Foo* foo) {
550 foos_.push_back(foo);
551 }
552
Observe(int x)553 void Observe(int x) override {
554 std::vector<Foo*> tmp;
555 tmp.swap(foos_);
556 for (std::vector<Foo*>::iterator it = tmp.begin();
557 it != tmp.end(); ++it) {
558 list_->RemoveObserver(*it);
559 }
560 }
561
562 private:
563 const scoped_refptr<ObserverListThreadSafe<Foo> > list_;
564 std::vector<Foo*> foos_;
565 };
566
TEST(ObserverListThreadSafeTest,RemoveMultipleObservers)567 TEST(ObserverListThreadSafeTest, RemoveMultipleObservers) {
568 MessageLoop loop;
569 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
570 new ObserverListThreadSafe<Foo>);
571
572 FooRemover a(observer_list.get());
573 Adder b(1);
574
575 observer_list->AddObserver(&a);
576 observer_list->AddObserver(&b);
577
578 a.AddFooToRemove(&a);
579 a.AddFooToRemove(&b);
580
581 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
582 RunLoop().RunUntilIdle();
583 }
584
585 // A test driver for a multi-threaded notification loop. Runs a number
586 // of observer threads, each of which constantly adds/removes itself
587 // from the observer list. Optionally, if cross_thread_notifies is set
588 // to true, the observer threads will also trigger notifications to
589 // all observers.
ThreadSafeObserverHarness(int num_threads,bool cross_thread_notifies)590 static void ThreadSafeObserverHarness(int num_threads,
591 bool cross_thread_notifies) {
592 MessageLoop loop;
593
594 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
595 new ObserverListThreadSafe<Foo>);
596 Adder a(1);
597 Adder b(-1);
598
599 observer_list->AddObserver(&a);
600 observer_list->AddObserver(&b);
601
602 std::vector<AddRemoveThread*> threaded_observer;
603 std::vector<base::PlatformThreadHandle> threads(num_threads);
604 std::vector<std::unique_ptr<base::WaitableEvent>> ready;
605 threaded_observer.reserve(num_threads);
606 ready.reserve(num_threads);
607 for (int index = 0; index < num_threads; index++) {
608 ready.push_back(std::make_unique<WaitableEvent>(
609 WaitableEvent::ResetPolicy::MANUAL,
610 WaitableEvent::InitialState::NOT_SIGNALED));
611 threaded_observer.push_back(new AddRemoveThread(
612 observer_list.get(), cross_thread_notifies, ready.back().get()));
613 EXPECT_TRUE(
614 PlatformThread::Create(0, threaded_observer.back(), &threads[index]));
615 }
616 ASSERT_EQ(static_cast<size_t>(num_threads), threaded_observer.size());
617 ASSERT_EQ(static_cast<size_t>(num_threads), ready.size());
618
619 // This makes sure that threaded_observer has gotten to set loop_, so that we
620 // can call Quit() below safe-ish-ly.
621 for (int i = 0; i < num_threads; ++i)
622 ready[i]->Wait();
623
624 Time start = Time::Now();
625 while (true) {
626 if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
627 break;
628
629 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
630
631 RunLoop().RunUntilIdle();
632 }
633
634 for (int index = 0; index < num_threads; index++) {
635 threaded_observer[index]->Quit();
636 PlatformThread::Join(threads[index]);
637 }
638 }
639
640 #if defined(OS_FUCHSIA)
641 // TODO(crbug.com/738275): This is flaky on Fuchsia.
642 #define MAYBE_CrossThreadObserver DISABLED_CrossThreadObserver
643 #else
644 #define MAYBE_CrossThreadObserver CrossThreadObserver
645 #endif
TEST(ObserverListThreadSafeTest,MAYBE_CrossThreadObserver)646 TEST(ObserverListThreadSafeTest, MAYBE_CrossThreadObserver) {
647 // Use 7 observer threads. Notifications only come from
648 // the main thread.
649 ThreadSafeObserverHarness(7, false);
650 }
651
TEST(ObserverListThreadSafeTest,CrossThreadNotifications)652 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) {
653 // Use 3 observer threads. Notifications will fire from
654 // the main thread and all 3 observer threads.
655 ThreadSafeObserverHarness(3, true);
656 }
657
TEST(ObserverListThreadSafeTest,OutlivesMessageLoop)658 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) {
659 MessageLoop* loop = new MessageLoop;
660 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
661 new ObserverListThreadSafe<Foo>);
662
663 Adder a(1);
664 observer_list->AddObserver(&a);
665 delete loop;
666 // Test passes if we don't crash here.
667 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
668 }
669
670 namespace {
671
672 class SequenceVerificationObserver : public Foo {
673 public:
SequenceVerificationObserver(scoped_refptr<SequencedTaskRunner> task_runner)674 explicit SequenceVerificationObserver(
675 scoped_refptr<SequencedTaskRunner> task_runner)
676 : task_runner_(std::move(task_runner)) {}
677 ~SequenceVerificationObserver() override = default;
678
Observe(int x)679 void Observe(int x) override {
680 called_on_valid_sequence_ = task_runner_->RunsTasksInCurrentSequence();
681 }
682
called_on_valid_sequence() const683 bool called_on_valid_sequence() const { return called_on_valid_sequence_; }
684
685 private:
686 const scoped_refptr<SequencedTaskRunner> task_runner_;
687 bool called_on_valid_sequence_ = false;
688
689 DISALLOW_COPY_AND_ASSIGN(SequenceVerificationObserver);
690 };
691
692 } // namespace
693
694 // Verify that observers are notified on the correct sequence.
695 // TaskScheduler not supported in libchrome
696 #if 0
697 TEST(ObserverListThreadSafeTest, NotificationOnValidSequence) {
698 test::ScopedTaskEnvironment scoped_task_environment;
699
700 auto task_runner_1 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
701 auto task_runner_2 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
702
703 auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
704
705 SequenceVerificationObserver observer_1(task_runner_1);
706 SequenceVerificationObserver observer_2(task_runner_2);
707
708 task_runner_1->PostTask(FROM_HERE,
709 BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
710 observer_list, Unretained(&observer_1)));
711 task_runner_2->PostTask(FROM_HERE,
712 BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
713 observer_list, Unretained(&observer_2)));
714
715 TaskScheduler::GetInstance()->FlushForTesting();
716
717 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
718
719 TaskScheduler::GetInstance()->FlushForTesting();
720
721 EXPECT_TRUE(observer_1.called_on_valid_sequence());
722 EXPECT_TRUE(observer_2.called_on_valid_sequence());
723 }
724 #endif
725
726 // Verify that when an observer is added to a NOTIFY_ALL ObserverListThreadSafe
727 // from a notification, it is itself notified.
728 // TaskScheduler not supported in libchrome
729 #if 0
730 TEST(ObserverListThreadSafeTest, AddObserverFromNotificationNotifyAll) {
731 test::ScopedTaskEnvironment scoped_task_environment;
732 auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
733
734 Adder observer_added_from_notification(1);
735
736 AddInObserve<ObserverListThreadSafe<Foo>> initial_observer(
737 observer_list.get());
738 initial_observer.SetToAdd(&observer_added_from_notification);
739 observer_list->AddObserver(&initial_observer);
740
741 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
742
743 base::RunLoop().RunUntilIdle();
744
745 EXPECT_EQ(1, observer_added_from_notification.GetValue());
746 }
747 #endif
748
749 namespace {
750
751 class RemoveWhileNotificationIsRunningObserver : public Foo {
752 public:
RemoveWhileNotificationIsRunningObserver()753 RemoveWhileNotificationIsRunningObserver()
754 : notification_running_(WaitableEvent::ResetPolicy::AUTOMATIC,
755 WaitableEvent::InitialState::NOT_SIGNALED),
756 barrier_(WaitableEvent::ResetPolicy::AUTOMATIC,
757 WaitableEvent::InitialState::NOT_SIGNALED) {}
758 ~RemoveWhileNotificationIsRunningObserver() override = default;
759
Observe(int x)760 void Observe(int x) override {
761 notification_running_.Signal();
762 ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
763 barrier_.Wait();
764 }
765
WaitForNotificationRunning()766 void WaitForNotificationRunning() { notification_running_.Wait(); }
Unblock()767 void Unblock() { barrier_.Signal(); }
768
769 private:
770 WaitableEvent notification_running_;
771 WaitableEvent barrier_;
772
773 DISALLOW_COPY_AND_ASSIGN(RemoveWhileNotificationIsRunningObserver);
774 };
775
776 } // namespace
777
778 // Verify that there is no crash when an observer is removed while it is being
779 // notified.
780 // TaskScheduler not supported in libchrome
781 #if 0
782 TEST(ObserverListThreadSafeTest, RemoveWhileNotificationIsRunning) {
783 auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
784 RemoveWhileNotificationIsRunningObserver observer;
785
786 WaitableEvent task_running(WaitableEvent::ResetPolicy::AUTOMATIC,
787 WaitableEvent::InitialState::NOT_SIGNALED);
788 WaitableEvent barrier(WaitableEvent::ResetPolicy::AUTOMATIC,
789 WaitableEvent::InitialState::NOT_SIGNALED);
790
791 // This must be after the declaration of |barrier| so that tasks posted to
792 // TaskScheduler can safely use |barrier|.
793 test::ScopedTaskEnvironment scoped_task_environment;
794
795 CreateSequencedTaskRunnerWithTraits({})->PostTask(
796 FROM_HERE, base::BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
797 observer_list, Unretained(&observer)));
798 TaskScheduler::GetInstance()->FlushForTesting();
799
800 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
801 observer.WaitForNotificationRunning();
802 observer_list->RemoveObserver(&observer);
803
804 observer.Unblock();
805 }
806 #endif
807
TEST(ObserverListTest,Existing)808 TEST(ObserverListTest, Existing) {
809 ObserverList<Foo> observer_list(ObserverListPolicy::EXISTING_ONLY);
810 Adder a(1);
811 AddInObserve<ObserverList<Foo> > b(&observer_list);
812 Adder c(1);
813 b.SetToAdd(&c);
814
815 observer_list.AddObserver(&a);
816 observer_list.AddObserver(&b);
817
818 for (auto& observer : observer_list)
819 observer.Observe(1);
820
821 EXPECT_FALSE(b.to_add_);
822 // B's adder should not have been notified because it was added during
823 // notification.
824 EXPECT_EQ(0, c.total);
825
826 // Notify again to make sure b's adder is notified.
827 for (auto& observer : observer_list)
828 observer.Observe(1);
829 EXPECT_EQ(1, c.total);
830 }
831
832 // Same as above, but for ObserverListThreadSafe
TEST(ObserverListThreadSafeTest,Existing)833 TEST(ObserverListThreadSafeTest, Existing) {
834 MessageLoop loop;
835 scoped_refptr<ObserverListThreadSafe<Foo>> observer_list(
836 new ObserverListThreadSafe<Foo>(ObserverListPolicy::EXISTING_ONLY));
837 Adder a(1);
838 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get());
839 Adder c(1);
840 b.SetToAdd(&c);
841
842 observer_list->AddObserver(&a);
843 observer_list->AddObserver(&b);
844
845 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
846 RunLoop().RunUntilIdle();
847
848 EXPECT_FALSE(b.to_add_);
849 // B's adder should not have been notified because it was added during
850 // notification.
851 EXPECT_EQ(0, c.total);
852
853 // Notify again to make sure b's adder is notified.
854 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
855 RunLoop().RunUntilIdle();
856 EXPECT_EQ(1, c.total);
857 }
858
859 class AddInClearObserve : public Foo {
860 public:
AddInClearObserve(ObserverList<Foo> * list)861 explicit AddInClearObserve(ObserverList<Foo>* list)
862 : list_(list), added_(false), adder_(1) {}
863
Observe(int)864 void Observe(int /* x */) override {
865 list_->Clear();
866 list_->AddObserver(&adder_);
867 added_ = true;
868 }
869
added() const870 bool added() const { return added_; }
adder() const871 const Adder& adder() const { return adder_; }
872
873 private:
874 ObserverList<Foo>* const list_;
875
876 bool added_;
877 Adder adder_;
878 };
879
TEST(ObserverListTest,ClearNotifyAll)880 TEST(ObserverListTest, ClearNotifyAll) {
881 ObserverList<Foo> observer_list;
882 AddInClearObserve a(&observer_list);
883
884 observer_list.AddObserver(&a);
885
886 for (auto& observer : observer_list)
887 observer.Observe(1);
888 EXPECT_TRUE(a.added());
889 EXPECT_EQ(1, a.adder().total)
890 << "Adder should observe once and have sum of 1.";
891 }
892
TEST(ObserverListTest,ClearNotifyExistingOnly)893 TEST(ObserverListTest, ClearNotifyExistingOnly) {
894 ObserverList<Foo> observer_list(ObserverListPolicy::EXISTING_ONLY);
895 AddInClearObserve a(&observer_list);
896
897 observer_list.AddObserver(&a);
898
899 for (auto& observer : observer_list)
900 observer.Observe(1);
901 EXPECT_TRUE(a.added());
902 EXPECT_EQ(0, a.adder().total)
903 << "Adder should not observe, so sum should still be 0.";
904 }
905
906 class ListDestructor : public Foo {
907 public:
ListDestructor(ObserverList<Foo> * list)908 explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {}
909 ~ListDestructor() override = default;
910
Observe(int x)911 void Observe(int x) override { delete list_; }
912
913 private:
914 ObserverList<Foo>* list_;
915 };
916
917
TEST(ObserverListTest,IteratorOutlivesList)918 TEST(ObserverListTest, IteratorOutlivesList) {
919 ObserverList<Foo>* observer_list = new ObserverList<Foo>;
920 ListDestructor a(observer_list);
921 observer_list->AddObserver(&a);
922
923 for (auto& observer : *observer_list)
924 observer.Observe(0);
925
926 // There are no EXPECT* statements for this test, if we catch
927 // use-after-free errors for observer_list (eg with ASan) then
928 // this test has failed. See http://crbug.com/85296.
929 }
930
TEST(ObserverListTest,BasicStdIterator)931 TEST(ObserverListTest, BasicStdIterator) {
932 using FooList = ObserverList<Foo>;
933 FooList observer_list;
934
935 // An optimization: begin() and end() do not involve weak pointers on
936 // empty list.
937 EXPECT_FALSE(observer_list.begin().list_);
938 EXPECT_FALSE(observer_list.end().list_);
939
940 // Iterate over empty list: no effect, no crash.
941 for (auto& i : observer_list)
942 i.Observe(10);
943
944 Adder a(1), b(-1), c(1), d(-1);
945
946 observer_list.AddObserver(&a);
947 observer_list.AddObserver(&b);
948 observer_list.AddObserver(&c);
949 observer_list.AddObserver(&d);
950
951 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
952 i != e; ++i)
953 i->Observe(1);
954
955 EXPECT_EQ(1, a.total);
956 EXPECT_EQ(-1, b.total);
957 EXPECT_EQ(1, c.total);
958 EXPECT_EQ(-1, d.total);
959
960 // Check an iteration over a 'const view' for a given container.
961 const FooList& const_list = observer_list;
962 for (FooList::const_iterator i = const_list.begin(), e = const_list.end();
963 i != e; ++i) {
964 EXPECT_EQ(1, std::abs(i->GetValue()));
965 }
966
967 for (const auto& o : const_list)
968 EXPECT_EQ(1, std::abs(o.GetValue()));
969 }
970
TEST(ObserverListTest,StdIteratorRemoveItself)971 TEST(ObserverListTest, StdIteratorRemoveItself) {
972 ObserverList<Foo> observer_list;
973 Adder a(1), b(-1), c(1), d(-1);
974 Disrupter disrupter(&observer_list, true);
975
976 observer_list.AddObserver(&a);
977 observer_list.AddObserver(&b);
978 observer_list.AddObserver(&disrupter);
979 observer_list.AddObserver(&c);
980 observer_list.AddObserver(&d);
981
982 for (auto& o : observer_list)
983 o.Observe(1);
984
985 for (auto& o : observer_list)
986 o.Observe(10);
987
988 EXPECT_EQ(11, a.total);
989 EXPECT_EQ(-11, b.total);
990 EXPECT_EQ(11, c.total);
991 EXPECT_EQ(-11, d.total);
992 }
993
TEST(ObserverListTest,StdIteratorRemoveBefore)994 TEST(ObserverListTest, StdIteratorRemoveBefore) {
995 ObserverList<Foo> observer_list;
996 Adder a(1), b(-1), c(1), d(-1);
997 Disrupter disrupter(&observer_list, &b);
998
999 observer_list.AddObserver(&a);
1000 observer_list.AddObserver(&b);
1001 observer_list.AddObserver(&disrupter);
1002 observer_list.AddObserver(&c);
1003 observer_list.AddObserver(&d);
1004
1005 for (auto& o : observer_list)
1006 o.Observe(1);
1007
1008 for (auto& o : observer_list)
1009 o.Observe(10);
1010
1011 EXPECT_EQ(11, a.total);
1012 EXPECT_EQ(-1, b.total);
1013 EXPECT_EQ(11, c.total);
1014 EXPECT_EQ(-11, d.total);
1015 }
1016
TEST(ObserverListTest,StdIteratorRemoveAfter)1017 TEST(ObserverListTest, StdIteratorRemoveAfter) {
1018 ObserverList<Foo> observer_list;
1019 Adder a(1), b(-1), c(1), d(-1);
1020 Disrupter disrupter(&observer_list, &c);
1021
1022 observer_list.AddObserver(&a);
1023 observer_list.AddObserver(&b);
1024 observer_list.AddObserver(&disrupter);
1025 observer_list.AddObserver(&c);
1026 observer_list.AddObserver(&d);
1027
1028 for (auto& o : observer_list)
1029 o.Observe(1);
1030
1031 for (auto& o : observer_list)
1032 o.Observe(10);
1033
1034 EXPECT_EQ(11, a.total);
1035 EXPECT_EQ(-11, b.total);
1036 EXPECT_EQ(0, c.total);
1037 EXPECT_EQ(-11, d.total);
1038 }
1039
TEST(ObserverListTest,StdIteratorRemoveAfterFront)1040 TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
1041 ObserverList<Foo> observer_list;
1042 Adder a(1), b(-1), c(1), d(-1);
1043 Disrupter disrupter(&observer_list, &a);
1044
1045 observer_list.AddObserver(&a);
1046 observer_list.AddObserver(&disrupter);
1047 observer_list.AddObserver(&b);
1048 observer_list.AddObserver(&c);
1049 observer_list.AddObserver(&d);
1050
1051 for (auto& o : observer_list)
1052 o.Observe(1);
1053
1054 for (auto& o : observer_list)
1055 o.Observe(10);
1056
1057 EXPECT_EQ(1, a.total);
1058 EXPECT_EQ(-11, b.total);
1059 EXPECT_EQ(11, c.total);
1060 EXPECT_EQ(-11, d.total);
1061 }
1062
TEST(ObserverListTest,StdIteratorRemoveBeforeBack)1063 TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
1064 ObserverList<Foo> observer_list;
1065 Adder a(1), b(-1), c(1), d(-1);
1066 Disrupter disrupter(&observer_list, &d);
1067
1068 observer_list.AddObserver(&a);
1069 observer_list.AddObserver(&b);
1070 observer_list.AddObserver(&c);
1071 observer_list.AddObserver(&disrupter);
1072 observer_list.AddObserver(&d);
1073
1074 for (auto& o : observer_list)
1075 o.Observe(1);
1076
1077 for (auto& o : observer_list)
1078 o.Observe(10);
1079
1080 EXPECT_EQ(11, a.total);
1081 EXPECT_EQ(-11, b.total);
1082 EXPECT_EQ(11, c.total);
1083 EXPECT_EQ(0, d.total);
1084 }
1085
TEST(ObserverListTest,StdIteratorRemoveFront)1086 TEST(ObserverListTest, StdIteratorRemoveFront) {
1087 using FooList = ObserverList<Foo>;
1088 FooList observer_list;
1089 Adder a(1), b(-1), c(1), d(-1);
1090 Disrupter disrupter(&observer_list, true);
1091
1092 observer_list.AddObserver(&disrupter);
1093 observer_list.AddObserver(&a);
1094 observer_list.AddObserver(&b);
1095 observer_list.AddObserver(&c);
1096 observer_list.AddObserver(&d);
1097
1098 bool test_disruptor = true;
1099 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
1100 i != e; ++i) {
1101 i->Observe(1);
1102 // Check that second call to i->Observe() would crash here.
1103 if (test_disruptor) {
1104 EXPECT_FALSE(i.GetCurrent());
1105 test_disruptor = false;
1106 }
1107 }
1108
1109 for (auto& o : observer_list)
1110 o.Observe(10);
1111
1112 EXPECT_EQ(11, a.total);
1113 EXPECT_EQ(-11, b.total);
1114 EXPECT_EQ(11, c.total);
1115 EXPECT_EQ(-11, d.total);
1116 }
1117
TEST(ObserverListTest,StdIteratorRemoveBack)1118 TEST(ObserverListTest, StdIteratorRemoveBack) {
1119 ObserverList<Foo> observer_list;
1120 Adder a(1), b(-1), c(1), d(-1);
1121 Disrupter disrupter(&observer_list, true);
1122
1123 observer_list.AddObserver(&a);
1124 observer_list.AddObserver(&b);
1125 observer_list.AddObserver(&c);
1126 observer_list.AddObserver(&d);
1127 observer_list.AddObserver(&disrupter);
1128
1129 for (auto& o : observer_list)
1130 o.Observe(1);
1131
1132 for (auto& o : observer_list)
1133 o.Observe(10);
1134
1135 EXPECT_EQ(11, a.total);
1136 EXPECT_EQ(-11, b.total);
1137 EXPECT_EQ(11, c.total);
1138 EXPECT_EQ(-11, d.total);
1139 }
1140
TEST(ObserverListTest,NestedLoop)1141 TEST(ObserverListTest, NestedLoop) {
1142 ObserverList<Foo> observer_list;
1143 Adder a(1), b(-1), c(1), d(-1);
1144 Disrupter disrupter(&observer_list, true);
1145
1146 observer_list.AddObserver(&disrupter);
1147 observer_list.AddObserver(&a);
1148 observer_list.AddObserver(&b);
1149 observer_list.AddObserver(&c);
1150 observer_list.AddObserver(&d);
1151
1152 for (auto& o : observer_list) {
1153 o.Observe(10);
1154
1155 for (auto& o : observer_list)
1156 o.Observe(1);
1157 }
1158
1159 EXPECT_EQ(15, a.total);
1160 EXPECT_EQ(-15, b.total);
1161 EXPECT_EQ(15, c.total);
1162 EXPECT_EQ(-15, d.total);
1163 }
1164
TEST(ObserverListTest,NonCompactList)1165 TEST(ObserverListTest, NonCompactList) {
1166 ObserverList<Foo> observer_list;
1167 Adder a(1), b(-1);
1168
1169 Disrupter disrupter1(&observer_list, true);
1170 Disrupter disrupter2(&observer_list, true);
1171
1172 // Disrupt itself and another one.
1173 disrupter1.SetDoomed(&disrupter2);
1174
1175 observer_list.AddObserver(&disrupter1);
1176 observer_list.AddObserver(&disrupter2);
1177 observer_list.AddObserver(&a);
1178 observer_list.AddObserver(&b);
1179
1180 for (auto& o : observer_list) {
1181 // Get the { nullptr, nullptr, &a, &b } non-compact list
1182 // on the first inner pass.
1183 o.Observe(10);
1184
1185 for (auto& o : observer_list)
1186 o.Observe(1);
1187 }
1188
1189 EXPECT_EQ(13, a.total);
1190 EXPECT_EQ(-13, b.total);
1191 }
1192
TEST(ObserverListTest,BecomesEmptyThanNonEmpty)1193 TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
1194 ObserverList<Foo> observer_list;
1195 Adder a(1), b(-1);
1196
1197 Disrupter disrupter1(&observer_list, true);
1198 Disrupter disrupter2(&observer_list, true);
1199
1200 // Disrupt itself and another one.
1201 disrupter1.SetDoomed(&disrupter2);
1202
1203 observer_list.AddObserver(&disrupter1);
1204 observer_list.AddObserver(&disrupter2);
1205
1206 bool add_observers = true;
1207 for (auto& o : observer_list) {
1208 // Get the { nullptr, nullptr } empty list on the first inner pass.
1209 o.Observe(10);
1210
1211 for (auto& o : observer_list)
1212 o.Observe(1);
1213
1214 if (add_observers) {
1215 observer_list.AddObserver(&a);
1216 observer_list.AddObserver(&b);
1217 add_observers = false;
1218 }
1219 }
1220
1221 EXPECT_EQ(12, a.total);
1222 EXPECT_EQ(-12, b.total);
1223 }
1224
TEST(ObserverListTest,AddObserverInTheLastObserve)1225 TEST(ObserverListTest, AddObserverInTheLastObserve) {
1226 using FooList = ObserverList<Foo>;
1227 FooList observer_list;
1228
1229 AddInObserve<FooList> a(&observer_list);
1230 Adder b(-1);
1231
1232 a.SetToAdd(&b);
1233 observer_list.AddObserver(&a);
1234
1235 auto it = observer_list.begin();
1236 while (it != observer_list.end()) {
1237 auto& observer = *it;
1238 // Intentionally increment the iterator before calling Observe(). The
1239 // ObserverList starts with only one observer, and it == observer_list.end()
1240 // should be true after the next line.
1241 ++it;
1242 // However, the first Observe() call will add a second observer: at this
1243 // point, it != observer_list.end() should be true, and Observe() should be
1244 // called on the newly added observer on the next iteration of the loop.
1245 observer.Observe(10);
1246 }
1247
1248 EXPECT_EQ(-10, b.total);
1249 }
1250
1251 class MockLogAssertHandler {
1252 public:
1253 MOCK_METHOD4(
1254 HandleLogAssert,
1255 void(const char*, int, const base::StringPiece, const base::StringPiece));
1256 };
1257
1258 #if DCHECK_IS_ON()
TEST(ObserverListTest,NonReentrantObserverList)1259 TEST(ObserverListTest, NonReentrantObserverList) {
1260 using ::testing::_;
1261
1262 ObserverList<Foo, /*check_empty=*/false, /*allow_reentrancy=*/false>
1263 non_reentrant_observer_list;
1264 Adder a(1);
1265 non_reentrant_observer_list.AddObserver(&a);
1266
1267 EXPECT_DCHECK_DEATH({
1268 for (const Foo& a : non_reentrant_observer_list) {
1269 for (const Foo& b : non_reentrant_observer_list) {
1270 std::ignore = a;
1271 std::ignore = b;
1272 }
1273 }
1274 });
1275 }
1276
TEST(ObserverListTest,ReentrantObserverList)1277 TEST(ObserverListTest, ReentrantObserverList) {
1278 using ::testing::_;
1279
1280 ReentrantObserverList<Foo> reentrant_observer_list;
1281 Adder a(1);
1282 reentrant_observer_list.AddObserver(&a);
1283 bool passed = false;
1284 for (const Foo& a : reentrant_observer_list) {
1285 for (const Foo& b : reentrant_observer_list) {
1286 std::ignore = a;
1287 std::ignore = b;
1288 passed = true;
1289 }
1290 }
1291 EXPECT_TRUE(passed);
1292 }
1293 #endif
1294
1295 } // namespace base
1296