| OLD | NEW | 
|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <iosfwd> | 5 #include <iosfwd> | 
| 6 #include <sstream> | 6 #include <sstream> | 
| 7 #include <string> | 7 #include <string> | 
| 8 #include <vector> | 8 #include <vector> | 
| 9 | 9 | 
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" | 
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" | 
| 12 #include "base/platform_thread.h" | 12 #include "base/platform_thread.h" | 
| 13 #include "base/port.h" | 13 #include "base/port.h" | 
| 14 #include "build/build_config.h" | 14 #include "build/build_config.h" | 
| 15 #include "chrome/common/deprecated/event_sys-inl.h" | 15 #include "chrome/common/deprecated/event_sys-inl.h" | 
| 16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" | 
| 17 | 17 | 
| 18 using std::endl; |  | 
| 19 using std::ostream; |  | 
| 20 using std::string; |  | 
| 21 using std::stringstream; |  | 
| 22 using std::vector; |  | 
| 23 |  | 
| 24 namespace { | 18 namespace { | 
| 25 | 19 | 
| 26 class Pair; | 20 class Pair; | 
| 27 | 21 | 
| 28 struct TestEvent { | 22 struct TestEvent { | 
| 29   Pair* source; | 23   Pair* source; | 
| 30   enum { | 24   enum { | 
| 31     A_CHANGED, B_CHANGED, PAIR_BEING_DELETED, | 25     A_CHANGED, B_CHANGED, PAIR_BEING_DELETED, | 
| 32   } what_happened; | 26   } what_happened; | 
| 33   int old_value; | 27   int old_value; | 
| 34 }; | 28 }; | 
| 35 | 29 | 
| 36 struct TestEventTraits { | 30 struct TestEventTraits { | 
| 37   typedef TestEvent EventType; | 31   typedef TestEvent EventType; | 
| 38   static bool IsChannelShutdownEvent(const TestEvent& event) { | 32   static bool IsChannelShutdownEvent(const TestEvent& event) { | 
| 39     return TestEvent::PAIR_BEING_DELETED == event.what_happened; | 33     return TestEvent::PAIR_BEING_DELETED == event.what_happened; | 
| 40   } | 34   } | 
| 41 }; | 35 }; | 
| 42 | 36 | 
| 43 class Pair { | 37 class Pair { | 
| 44  public: | 38  public: | 
| 45   typedef EventChannel<TestEventTraits> Channel; | 39   typedef EventChannel<TestEventTraits> Channel; | 
| 46   explicit Pair(const string& name) : name_(name), a_(0), b_(0) { | 40   explicit Pair(const std::string& name) : name_(name), a_(0), b_(0) { | 
| 47     TestEvent shutdown = { this, TestEvent::PAIR_BEING_DELETED, 0 }; | 41     TestEvent shutdown = { this, TestEvent::PAIR_BEING_DELETED, 0 }; | 
| 48     event_channel_ = new Channel(shutdown); | 42     event_channel_ = new Channel(shutdown); | 
| 49   } | 43   } | 
| 50   ~Pair() { | 44   ~Pair() { | 
| 51     delete event_channel_; | 45     delete event_channel_; | 
| 52   } | 46   } | 
| 53   void set_a(int n) { | 47   void set_a(int n) { | 
| 54     TestEvent event = { this, TestEvent::A_CHANGED, a_ }; | 48     TestEvent event = { this, TestEvent::A_CHANGED, a_ }; | 
| 55     a_ = n; | 49     a_ = n; | 
| 56     event_channel_->NotifyListeners(event); | 50     event_channel_->NotifyListeners(event); | 
| 57   } | 51   } | 
| 58   void set_b(int n) { | 52   void set_b(int n) { | 
| 59     TestEvent event = { this, TestEvent::B_CHANGED, b_ }; | 53     TestEvent event = { this, TestEvent::B_CHANGED, b_ }; | 
| 60     b_ = n; | 54     b_ = n; | 
| 61     event_channel_->NotifyListeners(event); | 55     event_channel_->NotifyListeners(event); | 
| 62   } | 56   } | 
| 63   int a() const { return a_; } | 57   int a() const { return a_; } | 
| 64   int b() const { return b_; } | 58   int b() const { return b_; } | 
| 65   const string& name() { return name_; } | 59   const std::string& name() { return name_; } | 
| 66   Channel* event_channel() const { return event_channel_; } | 60   Channel* event_channel() const { return event_channel_; } | 
| 67 | 61 | 
| 68  protected: | 62  protected: | 
| 69   const string name_; | 63   const std::string name_; | 
| 70   int a_; | 64   int a_; | 
| 71   int b_; | 65   int b_; | 
| 72   Channel* event_channel_; | 66   Channel* event_channel_; | 
| 73 }; | 67 }; | 
| 74 | 68 | 
| 75 class EventLogger { | 69 class EventLogger { | 
| 76  public: | 70  public: | 
| 77   explicit EventLogger(ostream& out) : out_(out) { } | 71   explicit EventLogger(std::ostream* out) : out_(out) { } | 
| 78   ~EventLogger() { | 72   ~EventLogger() { | 
| 79     for (Hookups::iterator i = hookups_.begin(); i != hookups_.end(); ++i) | 73     for (Hookups::iterator i = hookups_.begin(); i != hookups_.end(); ++i) | 
| 80       delete *i; | 74       delete *i; | 
| 81   } | 75   } | 
| 82 | 76 | 
| 83   void Hookup(const string name, Pair::Channel* channel) { | 77   void Hookup(const std::string name, Pair::Channel* channel) { | 
| 84     hookups_.push_back(NewEventListenerHookup(channel, this, | 78     hookups_.push_back(NewEventListenerHookup(channel, this, | 
| 85                                               &EventLogger::HandlePairEvent, | 79                                               &EventLogger::HandlePairEvent, | 
| 86                                               name)); | 80                                               name)); | 
| 87   } | 81   } | 
| 88 | 82 | 
| 89   void HandlePairEvent(const string& name, const TestEvent& event) { | 83   void HandlePairEvent(const std::string& name, const TestEvent& event) { | 
| 90     const char* what_changed = NULL; | 84     const char* what_changed = NULL; | 
| 91     int new_value = 0; | 85     int new_value = 0; | 
| 92     Hookups::iterator dead; | 86     Hookups::iterator dead; | 
| 93     switch (event.what_happened) { | 87     switch (event.what_happened) { | 
| 94     case TestEvent::A_CHANGED: | 88     case TestEvent::A_CHANGED: | 
| 95       what_changed = "A"; | 89       what_changed = "A"; | 
| 96       new_value = event.source->a(); | 90       new_value = event.source->a(); | 
| 97       break; | 91       break; | 
| 98     case TestEvent::B_CHANGED: | 92     case TestEvent::B_CHANGED: | 
| 99       what_changed = "B"; | 93       what_changed = "B"; | 
| 100       new_value = event.source->b(); | 94       new_value = event.source->b(); | 
| 101       break; | 95       break; | 
| 102     case TestEvent::PAIR_BEING_DELETED: | 96     case TestEvent::PAIR_BEING_DELETED: | 
| 103       out_ << name << " heard " << event.source->name() << " being deleted." | 97       *out_ << name << " heard " << event.source->name() << " being deleted." | 
| 104            << endl; | 98             << std::endl; | 
| 105       return; | 99       return; | 
| 106     default: | 100     default: | 
| 107       FAIL() << "Bad event.what_happened: " << event.what_happened; | 101       FAIL() << "Bad event.what_happened: " << event.what_happened; | 
| 108       break; | 102       break; | 
| 109     } | 103     } | 
| 110     out_ << name << " heard " << event.source->name() << "'s " << what_changed | 104     *out_ << name << " heard " << event.source->name() << "'s " << what_changed | 
| 111          << " change from " | 105           << " change from " << event.old_value | 
| 112          << event.old_value << " to " << new_value << endl; | 106           << " to " << new_value << std::endl; | 
| 113   } | 107   } | 
| 114 | 108 | 
| 115   typedef vector<EventListenerHookup*> Hookups; | 109   typedef std::vector<EventListenerHookup*> Hookups; | 
| 116   Hookups hookups_; | 110   Hookups hookups_; | 
| 117   ostream& out_; | 111   std::ostream* out_; | 
| 118 }; | 112 }; | 
| 119 | 113 | 
| 120 const char golden_result[] = "Larry heard Sally's B change from 0 to 2\n" | 114 const char golden_result[] = "Larry heard Sally's B change from 0 to 2\n" | 
| 121 "Larry heard Sally's A change from 1 to 3\n" | 115 "Larry heard Sally's A change from 1 to 3\n" | 
| 122 "Lewis heard Sam's B change from 0 to 5\n" | 116 "Lewis heard Sam's B change from 0 to 5\n" | 
| 123 "Larry heard Sally's A change from 3 to 6\n" | 117 "Larry heard Sally's A change from 3 to 6\n" | 
| 124 "Larry heard Sally being deleted.\n"; | 118 "Larry heard Sally being deleted.\n"; | 
| 125 | 119 | 
| 126 TEST(EventSys, Basic) { | 120 TEST(EventSys, Basic) { | 
| 127   Pair sally("Sally"), sam("Sam"); | 121   Pair sally("Sally"), sam("Sam"); | 
| 128   sally.set_a(1); | 122   sally.set_a(1); | 
| 129   stringstream log; | 123   std::stringstream log; | 
| 130   EventLogger logger(log); | 124   EventLogger logger(&log); | 
| 131   logger.Hookup("Larry", sally.event_channel()); | 125   logger.Hookup("Larry", sally.event_channel()); | 
| 132   sally.set_b(2); | 126   sally.set_b(2); | 
| 133   sally.set_a(3); | 127   sally.set_a(3); | 
| 134   sam.set_a(4); | 128   sam.set_a(4); | 
| 135   logger.Hookup("Lewis", sam.event_channel()); | 129   logger.Hookup("Lewis", sam.event_channel()); | 
| 136   sam.set_b(5); | 130   sam.set_b(5); | 
| 137   sally.set_a(6); | 131   sally.set_a(6); | 
| 138   // Test that disconnect within callback doesn't deadlock. | 132   // Test that disconnect within callback doesn't deadlock. | 
| 139   TestEvent event = {&sally, TestEvent::PAIR_BEING_DELETED, 0 }; | 133   TestEvent event = {&sally, TestEvent::PAIR_BEING_DELETED, 0 }; | 
| 140   sally.event_channel()->NotifyListeners(event); | 134   sally.event_channel()->NotifyListeners(event); | 
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 229       FAIL() << "A test thread exited too early."; | 223       FAIL() << "A test thread exited too early."; | 
| 230     completed_mutex_.Release(); | 224     completed_mutex_.Release(); | 
| 231   } | 225   } | 
| 232 | 226 | 
| 233   Pair* pair_; | 227   Pair* pair_; | 
| 234   ConditionVariable remove_event_; | 228   ConditionVariable remove_event_; | 
| 235   Lock remove_event_mutex_; | 229   Lock remove_event_mutex_; | 
| 236   bool remove_event_bool_; | 230   bool remove_event_bool_; | 
| 237   Lock completed_mutex_; | 231   Lock completed_mutex_; | 
| 238   bool completed_; | 232   bool completed_; | 
| 239   vector<ThreadInfo> threads_; | 233   std::vector<ThreadInfo> threads_; | 
| 240   ThreadArgs args_; | 234   ThreadArgs args_; | 
| 241 }; | 235 }; | 
| 242 | 236 | 
| 243 TEST(EventSys, Multithreaded) { | 237 TEST(EventSys, Multithreaded) { | 
| 244   Pair sally("Sally"); | 238   Pair sally("Sally"); | 
| 245   ThreadTester a(&sally); | 239   ThreadTester a(&sally); | 
| 246   for (int i = 0; i < 3; ++i) | 240   for (int i = 0; i < 3; ++i) | 
| 247     a.Go(); | 241     a.Go(); | 
| 248   sally.set_b(99); | 242   sally.set_b(99); | 
| 249 } | 243 } | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 261   Pair sally("Sally"); | 255   Pair sally("Sally"); | 
| 262   HookupDeleter deleter; | 256   HookupDeleter deleter; | 
| 263   deleter.hookup_ = NewEventListenerHookup(sally.event_channel(), | 257   deleter.hookup_ = NewEventListenerHookup(sally.event_channel(), | 
| 264                                            &deleter, | 258                                            &deleter, | 
| 265                                            &HookupDeleter::HandleEvent); | 259                                            &HookupDeleter::HandleEvent); | 
| 266   sally.set_a(1); | 260   sally.set_a(1); | 
| 267   ASSERT_TRUE(NULL == deleter.hookup_); | 261   ASSERT_TRUE(NULL == deleter.hookup_); | 
| 268 } | 262 } | 
| 269 | 263 | 
| 270 }  // namespace | 264 }  // namespace | 
| OLD | NEW | 
|---|