Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: chrome/common/deprecated/event_sys_unittest.cc

Issue 7587009: sync: add DEPS files to subdirs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix include Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/common/deprecated/event_sys-inl.h ('k') | chrome/common/net/gaia/gaia_authenticator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <iosfwd>
6 #include <sstream>
7 #include <string>
8 #include <vector>
9
10 #include "base/basictypes.h"
11 #include "base/message_loop.h"
12 #include "base/port.h"
13 #include "base/threading/platform_thread.h"
14 #include "build/build_config.h"
15 #include "chrome/common/deprecated/event_sys-inl.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace {
19
20 class Pair;
21
22 struct TestEvent {
23 Pair* source;
24 enum {
25 A_CHANGED, B_CHANGED, PAIR_BEING_DELETED,
26 } what_happened;
27 int old_value;
28 };
29
30 struct TestEventTraits {
31 typedef TestEvent EventType;
32 static bool IsChannelShutdownEvent(const TestEvent& event) {
33 return TestEvent::PAIR_BEING_DELETED == event.what_happened;
34 }
35 };
36
37 class Pair {
38 public:
39 typedef EventChannel<TestEventTraits> Channel;
40 explicit Pair(const std::string& name) : name_(name), a_(0), b_(0) {
41 TestEvent shutdown = { this, TestEvent::PAIR_BEING_DELETED, 0 };
42 event_channel_ = new Channel(shutdown);
43 }
44 ~Pair() {
45 delete event_channel_;
46 }
47 void set_a(int n) {
48 TestEvent event = { this, TestEvent::A_CHANGED, a_ };
49 a_ = n;
50 event_channel_->NotifyListeners(event);
51 }
52 void set_b(int n) {
53 TestEvent event = { this, TestEvent::B_CHANGED, b_ };
54 b_ = n;
55 event_channel_->NotifyListeners(event);
56 }
57 int a() const { return a_; }
58 int b() const { return b_; }
59 const std::string& name() { return name_; }
60 Channel* event_channel() const { return event_channel_; }
61
62 protected:
63 const std::string name_;
64 int a_;
65 int b_;
66 Channel* event_channel_;
67 };
68
69 class EventLogger {
70 public:
71 explicit EventLogger(std::ostream* out) : out_(out) { }
72 ~EventLogger() {
73 for (Hookups::iterator i = hookups_.begin(); i != hookups_.end(); ++i)
74 delete *i;
75 }
76
77 void Hookup(const std::string name, Pair::Channel* channel) {
78 hookups_.push_back(NewEventListenerHookup(channel, this,
79 &EventLogger::HandlePairEvent,
80 name));
81 }
82
83 void HandlePairEvent(const std::string& name, const TestEvent& event) {
84 const char* what_changed = NULL;
85 int new_value = 0;
86 Hookups::iterator dead;
87 switch (event.what_happened) {
88 case TestEvent::A_CHANGED:
89 what_changed = "A";
90 new_value = event.source->a();
91 break;
92 case TestEvent::B_CHANGED:
93 what_changed = "B";
94 new_value = event.source->b();
95 break;
96 case TestEvent::PAIR_BEING_DELETED:
97 *out_ << name << " heard " << event.source->name() << " being deleted."
98 << std::endl;
99 return;
100 default:
101 FAIL() << "Bad event.what_happened: " << event.what_happened;
102 break;
103 }
104 *out_ << name << " heard " << event.source->name() << "'s " << what_changed
105 << " change from " << event.old_value
106 << " to " << new_value << std::endl;
107 }
108
109 typedef std::vector<EventListenerHookup*> Hookups;
110 Hookups hookups_;
111 std::ostream* out_;
112 };
113
114 const char golden_result[] = "Larry heard Sally's B change from 0 to 2\n"
115 "Larry heard Sally's A change from 1 to 3\n"
116 "Lewis heard Sam's B change from 0 to 5\n"
117 "Larry heard Sally's A change from 3 to 6\n"
118 "Larry heard Sally being deleted.\n";
119
120 TEST(EventSys, Basic) {
121 Pair sally("Sally"), sam("Sam");
122 sally.set_a(1);
123 std::stringstream log;
124 EventLogger logger(&log);
125 logger.Hookup("Larry", sally.event_channel());
126 sally.set_b(2);
127 sally.set_a(3);
128 sam.set_a(4);
129 logger.Hookup("Lewis", sam.event_channel());
130 sam.set_b(5);
131 sally.set_a(6);
132 // Test that disconnect within callback doesn't deadlock.
133 TestEvent event = {&sally, TestEvent::PAIR_BEING_DELETED, 0 };
134 sally.event_channel()->NotifyListeners(event);
135 sally.set_a(7);
136 ASSERT_EQ(log.str(), golden_result);
137 }
138
139
140 // This goes pretty far beyond the normal use pattern, so don't use
141 // ThreadTester as an example of what to do.
142 class ThreadTester : public EventListener<TestEvent>,
143 public base::PlatformThread::Delegate {
144 public:
145 explicit ThreadTester(Pair* pair)
146 : pair_(pair), remove_event_(&remove_event_mutex_),
147 remove_event_bool_(false), completed_(false) {
148 pair_->event_channel()->AddListener(this);
149 }
150 ~ThreadTester() {
151 pair_->event_channel()->RemoveListener(this);
152 for (size_t i = 0; i < threads_.size(); i++) {
153 base::PlatformThread::Join(threads_[i].thread);
154 }
155 }
156
157 struct ThreadInfo {
158 base::PlatformThreadHandle thread;
159 };
160
161 struct ThreadArgs {
162 base::ConditionVariable* thread_running_cond;
163 base::Lock* thread_running_mutex;
164 bool thread_running;
165 };
166
167 void Go() {
168 base::Lock thread_running_mutex;
169 base::ConditionVariable thread_running_cond(&thread_running_mutex);
170 ThreadArgs args;
171 ThreadInfo info;
172 args.thread_running_cond = &(thread_running_cond);
173 args.thread_running_mutex = &(thread_running_mutex);
174 args.thread_running = false;
175 args_ = args;
176 ASSERT_TRUE(base::PlatformThread::Create(0, this, &info.thread));
177 thread_running_mutex.Acquire();
178 while ((args_.thread_running) == false) {
179 thread_running_cond.Wait();
180 }
181 thread_running_mutex.Release();
182 threads_.push_back(info);
183 }
184
185 // PlatformThread::Delegate methods.
186 virtual void ThreadMain() {
187 // Make sure each thread gets a current MessageLoop in TLS.
188 // This test should use chrome threads for testing, but I'll leave it like
189 // this for the moment since it requires a big chunk of rewriting and I
190 // want the test passing while I checkpoint my CL. Technically speaking,
191 // there should be no functional difference.
192 MessageLoop message_loop;
193 args_.thread_running_mutex->Acquire();
194 args_.thread_running = true;
195 args_.thread_running_cond->Signal();
196 args_.thread_running_mutex->Release();
197
198 remove_event_mutex_.Acquire();
199 while (remove_event_bool_ == false) {
200 remove_event_.Wait();
201 }
202 remove_event_mutex_.Release();
203
204 // Normally, you'd just delete the hookup. This is very bad style, but
205 // necessary for the test.
206 pair_->event_channel()->RemoveListener(this);
207
208 completed_mutex_.Acquire();
209 completed_ = true;
210 completed_mutex_.Release();
211 }
212
213 void HandleEvent(const TestEvent& event) {
214 remove_event_mutex_.Acquire();
215 remove_event_bool_ = true;
216 remove_event_.Broadcast();
217 remove_event_mutex_.Release();
218
219 base::PlatformThread::YieldCurrentThread();
220
221 completed_mutex_.Acquire();
222 if (completed_)
223 FAIL() << "A test thread exited too early.";
224 completed_mutex_.Release();
225 }
226
227 Pair* pair_;
228 base::ConditionVariable remove_event_;
229 base::Lock remove_event_mutex_;
230 bool remove_event_bool_;
231 base::Lock completed_mutex_;
232 bool completed_;
233 std::vector<ThreadInfo> threads_;
234 ThreadArgs args_;
235 };
236
237 TEST(EventSys, Multithreaded) {
238 Pair sally("Sally");
239 ThreadTester a(&sally);
240 for (int i = 0; i < 3; ++i)
241 a.Go();
242 sally.set_b(99);
243 }
244
245 class HookupDeleter {
246 public:
247 void HandleEvent(const TestEvent& event) {
248 delete hookup_;
249 hookup_ = NULL;
250 }
251 EventListenerHookup* hookup_;
252 };
253
254 TEST(EventSys, InHandlerDeletion) {
255 Pair sally("Sally");
256 HookupDeleter deleter;
257 deleter.hookup_ = NewEventListenerHookup(sally.event_channel(),
258 &deleter,
259 &HookupDeleter::HandleEvent);
260 sally.set_a(1);
261 ASSERT_TRUE(NULL == deleter.hookup_);
262 }
263
264 } // namespace
OLDNEW
« no previous file with comments | « chrome/common/deprecated/event_sys-inl.h ('k') | chrome/common/net/gaia/gaia_authenticator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698