OLD | NEW |
| (Empty) |
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 "chrome/browser/net/chrome_net_log.h" | |
6 | |
7 #include "base/synchronization/waitable_event.h" | |
8 #include "base/threading/simple_thread.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | |
10 | |
11 namespace { | |
12 | |
13 const int kThreads = 10; | |
14 const int kEvents = 100; | |
15 | |
16 class CountingObserver : public net::NetLog::ThreadSafeObserver { | |
17 public: | |
18 CountingObserver() : count_(0) {} | |
19 | |
20 virtual ~CountingObserver() { | |
21 if (net_log()) | |
22 net_log()->RemoveThreadSafeObserver(this); | |
23 } | |
24 | |
25 virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE { | |
26 ++count_; | |
27 } | |
28 | |
29 int count() const { return count_; } | |
30 | |
31 private: | |
32 int count_; | |
33 }; | |
34 | |
35 void AddEvent(ChromeNetLog* net_log) { | |
36 net_log->AddGlobalEntry(net::NetLog::TYPE_CANCELLED); | |
37 } | |
38 | |
39 // A thread that waits until an event has been signalled before calling | |
40 // RunTestThread. | |
41 class ChromeNetLogTestThread : public base::SimpleThread { | |
42 public: | |
43 ChromeNetLogTestThread() : base::SimpleThread("ChromeNetLogTest"), | |
44 net_log_(NULL), | |
45 start_event_(NULL) { | |
46 } | |
47 | |
48 // We'll wait for |start_event| to be triggered before calling a subclass's | |
49 // subclass's RunTestThread() function. | |
50 void Init(ChromeNetLog* net_log, base::WaitableEvent* start_event) { | |
51 start_event_ = start_event; | |
52 net_log_ = net_log; | |
53 } | |
54 | |
55 virtual void Run() OVERRIDE { | |
56 start_event_->Wait(); | |
57 RunTestThread(); | |
58 } | |
59 | |
60 // Subclasses must override this with the code they want to run on their | |
61 // thread. | |
62 virtual void RunTestThread() = 0; | |
63 | |
64 protected: | |
65 ChromeNetLog* net_log_; | |
66 | |
67 private: | |
68 // Only triggered once all threads have been created, to make it less likely | |
69 // each thread completes before the next one starts. | |
70 base::WaitableEvent* start_event_; | |
71 | |
72 DISALLOW_COPY_AND_ASSIGN(ChromeNetLogTestThread); | |
73 }; | |
74 | |
75 // A thread that adds a bunch of events to the NetLog. | |
76 class AddEventsTestThread : public ChromeNetLogTestThread { | |
77 public: | |
78 AddEventsTestThread() {} | |
79 virtual ~AddEventsTestThread() {} | |
80 | |
81 private: | |
82 virtual void RunTestThread() OVERRIDE { | |
83 for (int i = 0; i < kEvents; ++i) | |
84 AddEvent(net_log_); | |
85 } | |
86 | |
87 DISALLOW_COPY_AND_ASSIGN(AddEventsTestThread); | |
88 }; | |
89 | |
90 // A thread that adds and removes an observer from the NetLog repeatedly. | |
91 class AddRemoveObserverTestThread : public ChromeNetLogTestThread { | |
92 public: | |
93 AddRemoveObserverTestThread() {} | |
94 | |
95 virtual ~AddRemoveObserverTestThread() { | |
96 EXPECT_TRUE(!observer_.net_log()); | |
97 } | |
98 | |
99 private: | |
100 virtual void RunTestThread() OVERRIDE { | |
101 for (int i = 0; i < kEvents; ++i) { | |
102 ASSERT_FALSE(observer_.net_log()); | |
103 | |
104 net_log_->AddThreadSafeObserver(&observer_, net::NetLog::LOG_BASIC); | |
105 ASSERT_EQ(net_log_, observer_.net_log()); | |
106 ASSERT_EQ(net::NetLog::LOG_BASIC, observer_.log_level()); | |
107 | |
108 net_log_->SetObserverLogLevel(&observer_, net::NetLog::LOG_ALL_BUT_BYTES); | |
109 ASSERT_EQ(net_log_, observer_.net_log()); | |
110 ASSERT_EQ(net::NetLog::LOG_ALL_BUT_BYTES, observer_.log_level()); | |
111 ASSERT_LE(net_log_->GetLogLevel(), net::NetLog::LOG_ALL_BUT_BYTES); | |
112 | |
113 net_log_->SetObserverLogLevel(&observer_, net::NetLog::LOG_ALL); | |
114 ASSERT_EQ(net_log_, observer_.net_log()); | |
115 ASSERT_EQ(net::NetLog::LOG_ALL, observer_.log_level()); | |
116 ASSERT_LE(net_log_->GetLogLevel(), net::NetLog::LOG_ALL); | |
117 | |
118 net_log_->RemoveThreadSafeObserver(&observer_); | |
119 ASSERT_TRUE(!observer_.net_log()); | |
120 } | |
121 } | |
122 | |
123 CountingObserver observer_; | |
124 | |
125 DISALLOW_COPY_AND_ASSIGN(AddRemoveObserverTestThread); | |
126 }; | |
127 | |
128 // Creates |kThreads| threads of type |ThreadType| and then runs them all | |
129 // to completion. | |
130 template<class ThreadType> | |
131 void RunTestThreads(ChromeNetLog* net_log) { | |
132 ThreadType threads[kThreads]; | |
133 base::WaitableEvent start_event(true, false); | |
134 | |
135 for (size_t i = 0; i < arraysize(threads); ++i) { | |
136 threads[i].Init(net_log, &start_event); | |
137 threads[i].Start(); | |
138 } | |
139 | |
140 start_event.Signal(); | |
141 | |
142 for (size_t i = 0; i < arraysize(threads); ++i) | |
143 threads[i].Join(); | |
144 } | |
145 | |
146 // Makes sure that events on multiple threads are dispatched to all observers. | |
147 TEST(ChromeNetLogTest, NetLogEventThreads) { | |
148 ChromeNetLog net_log; | |
149 | |
150 // Attach some observers. Since they're created after |net_log|, they'll | |
151 // safely detach themselves on destruction. | |
152 CountingObserver observers[3]; | |
153 for (size_t i = 0; i < arraysize(observers); ++i) | |
154 net_log.AddThreadSafeObserver(&observers[i], net::NetLog::LOG_BASIC); | |
155 | |
156 // Run a bunch of threads to completion, each of which will emit events to | |
157 // |net_log|. | |
158 RunTestThreads<AddEventsTestThread>(&net_log); | |
159 | |
160 // Check that each observer saw the emitted events. | |
161 const int kTotalEvents = kThreads * kEvents; | |
162 for (size_t i = 0; i < arraysize(observers); ++i) | |
163 EXPECT_EQ(kTotalEvents, observers[i].count()); | |
164 } | |
165 | |
166 // Test adding and removing a single observer. | |
167 TEST(ChromeNetLogTest, NetLogAddRemoveObserver) { | |
168 ChromeNetLog net_log; | |
169 CountingObserver observer; | |
170 | |
171 AddEvent(&net_log); | |
172 EXPECT_EQ(0, observer.count()); | |
173 EXPECT_EQ(NULL, observer.net_log()); | |
174 EXPECT_EQ(net::NetLog::LOG_NONE, net_log.GetLogLevel()); | |
175 | |
176 // Add the observer and add an event. | |
177 net_log.AddThreadSafeObserver(&observer, net::NetLog::LOG_BASIC); | |
178 EXPECT_EQ(&net_log, observer.net_log()); | |
179 EXPECT_EQ(net::NetLog::LOG_BASIC, observer.log_level()); | |
180 EXPECT_EQ(net::NetLog::LOG_BASIC, net_log.GetLogLevel()); | |
181 | |
182 AddEvent(&net_log); | |
183 EXPECT_EQ(1, observer.count()); | |
184 | |
185 // Change the observer's logging level and add an event. | |
186 net_log.SetObserverLogLevel(&observer, net::NetLog::LOG_ALL); | |
187 EXPECT_EQ(&net_log, observer.net_log()); | |
188 EXPECT_EQ(net::NetLog::LOG_ALL, observer.log_level()); | |
189 EXPECT_EQ(net::NetLog::LOG_ALL, net_log.GetLogLevel()); | |
190 | |
191 AddEvent(&net_log); | |
192 EXPECT_EQ(2, observer.count()); | |
193 | |
194 // Remove observer and add an event. | |
195 net_log.RemoveThreadSafeObserver(&observer); | |
196 EXPECT_EQ(NULL, observer.net_log()); | |
197 EXPECT_EQ(net::NetLog::LOG_NONE, net_log.GetLogLevel()); | |
198 | |
199 AddEvent(&net_log); | |
200 EXPECT_EQ(2, observer.count()); | |
201 | |
202 // Add the observer a final time, and add an event. | |
203 net_log.AddThreadSafeObserver(&observer, net::NetLog::LOG_ALL); | |
204 EXPECT_EQ(&net_log, observer.net_log()); | |
205 EXPECT_EQ(net::NetLog::LOG_ALL, observer.log_level()); | |
206 EXPECT_EQ(net::NetLog::LOG_ALL, net_log.GetLogLevel()); | |
207 | |
208 AddEvent(&net_log); | |
209 EXPECT_EQ(3, observer.count()); | |
210 } | |
211 | |
212 // Test adding and removing two observers. | |
213 TEST(ChromeNetLogTest, NetLogTwoObservers) { | |
214 ChromeNetLog net_log; | |
215 CountingObserver observer[2]; | |
216 | |
217 // Add first observer. | |
218 net_log.AddThreadSafeObserver(&observer[0], net::NetLog::LOG_ALL_BUT_BYTES); | |
219 EXPECT_EQ(&net_log, observer[0].net_log()); | |
220 EXPECT_EQ(NULL, observer[1].net_log()); | |
221 EXPECT_EQ(net::NetLog::LOG_ALL_BUT_BYTES, observer[0].log_level()); | |
222 EXPECT_EQ(net::NetLog::LOG_ALL_BUT_BYTES, net_log.GetLogLevel()); | |
223 | |
224 // Add second observer observer. | |
225 net_log.AddThreadSafeObserver(&observer[1], net::NetLog::LOG_ALL); | |
226 EXPECT_EQ(&net_log, observer[0].net_log()); | |
227 EXPECT_EQ(&net_log, observer[1].net_log()); | |
228 EXPECT_EQ(net::NetLog::LOG_ALL_BUT_BYTES, observer[0].log_level()); | |
229 EXPECT_EQ(net::NetLog::LOG_ALL, observer[1].log_level()); | |
230 EXPECT_EQ(net::NetLog::LOG_ALL, net_log.GetLogLevel()); | |
231 | |
232 // Add event and make sure both observers receive it. | |
233 AddEvent(&net_log); | |
234 EXPECT_EQ(1, observer[0].count()); | |
235 EXPECT_EQ(1, observer[1].count()); | |
236 | |
237 // Remove second observer. | |
238 net_log.RemoveThreadSafeObserver(&observer[1]); | |
239 EXPECT_EQ(&net_log, observer[0].net_log()); | |
240 EXPECT_EQ(NULL, observer[1].net_log()); | |
241 EXPECT_EQ(net::NetLog::LOG_ALL_BUT_BYTES, observer[0].log_level()); | |
242 EXPECT_EQ(net::NetLog::LOG_ALL_BUT_BYTES, net_log.GetLogLevel()); | |
243 | |
244 // Add event and make sure only second observer gets it. | |
245 AddEvent(&net_log); | |
246 EXPECT_EQ(2, observer[0].count()); | |
247 EXPECT_EQ(1, observer[1].count()); | |
248 | |
249 // Remove first observer. | |
250 net_log.RemoveThreadSafeObserver(&observer[0]); | |
251 EXPECT_EQ(NULL, observer[0].net_log()); | |
252 EXPECT_EQ(NULL, observer[1].net_log()); | |
253 EXPECT_EQ(net::NetLog::LOG_NONE, net_log.GetLogLevel()); | |
254 | |
255 // Add event and make sure neither observer gets it. | |
256 AddEvent(&net_log); | |
257 EXPECT_EQ(2, observer[0].count()); | |
258 EXPECT_EQ(1, observer[1].count()); | |
259 } | |
260 | |
261 // Makes sure that adding and removing observers simultaneously on different | |
262 // threads works. | |
263 TEST(ChromeNetLogTest, NetLogAddRemoveObserverThreads) { | |
264 ChromeNetLog net_log; | |
265 | |
266 // Run a bunch of threads to completion, each of which will repeatedly add | |
267 // and remove an observer, and set its logging level. | |
268 RunTestThreads<AddRemoveObserverTestThread>(&net_log); | |
269 } | |
270 | |
271 } // namespace | |
OLD | NEW |