1 // Copyright (c) 2013 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.
5 #include "net/log/net_log.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/threading/simple_thread.h"
11 #include "base/values.h"
12 #include "net/base/net_errors.h"
13 #include "net/log/test_net_log.h"
14 #include "net/log/test_net_log_entry.h"
15 #include "net/log/test_net_log_util.h"
21 const int kThreads
= 10;
22 const int kEvents
= 100;
24 // Under the hood a NetLogCaptureMode is simply an int. But for layering reasons
25 // this internal value is not exposed. These tests need to serialize a
26 // NetLogCaptureMode to a base::Value, so create our own private mapping.
27 int CaptureModeToInt(NetLogCaptureMode capture_mode
) {
28 if (capture_mode
== NetLogCaptureMode::Default())
30 if (capture_mode
== NetLogCaptureMode::IncludeCookiesAndCredentials())
32 if (capture_mode
== NetLogCaptureMode::IncludeSocketBytes())
35 ADD_FAILURE() << "Unknown capture mode";
39 scoped_ptr
<base::Value
> CaptureModeToValue(NetLogCaptureMode capture_mode
) {
40 return make_scoped_ptr(
41 new base::FundamentalValue(CaptureModeToInt(capture_mode
)));
44 scoped_ptr
<base::Value
> NetCaptureModeCallback(NetLogCaptureMode capture_mode
) {
45 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
46 dict
->Set("capture_mode", CaptureModeToValue(capture_mode
));
50 TEST(NetLogTest
, Basic
) {
52 TestNetLogEntry::List entries
;
53 net_log
.GetEntries(&entries
);
54 EXPECT_EQ(0u, entries
.size());
56 net_log
.AddGlobalEntry(NetLog::TYPE_CANCELLED
);
58 net_log
.GetEntries(&entries
);
59 ASSERT_EQ(1u, entries
.size());
60 EXPECT_EQ(NetLog::TYPE_CANCELLED
, entries
[0].type
);
61 EXPECT_EQ(NetLog::SOURCE_NONE
, entries
[0].source
.type
);
62 EXPECT_NE(NetLog::Source::kInvalidId
, entries
[0].source
.id
);
63 EXPECT_EQ(NetLog::PHASE_NONE
, entries
[0].phase
);
64 EXPECT_GE(base::TimeTicks::Now(), entries
[0].time
);
65 EXPECT_FALSE(entries
[0].params
);
68 // Check that the correct CaptureMode is sent to NetLog Value callbacks.
69 TEST(NetLogTest
, CaptureModes
) {
70 NetLogCaptureMode kModes
[] = {
71 NetLogCaptureMode::Default(),
72 NetLogCaptureMode::IncludeCookiesAndCredentials(),
73 NetLogCaptureMode::IncludeSocketBytes(),
78 for (NetLogCaptureMode mode
: kModes
) {
79 net_log
.SetCaptureMode(mode
);
80 EXPECT_EQ(mode
, net_log
.GetObserver()->capture_mode());
82 net_log
.AddGlobalEntry(NetLog::TYPE_SOCKET_ALIVE
,
83 base::Bind(NetCaptureModeCallback
));
85 TestNetLogEntry::List entries
;
86 net_log
.GetEntries(&entries
);
88 ASSERT_EQ(1u, entries
.size());
89 EXPECT_EQ(NetLog::TYPE_SOCKET_ALIVE
, entries
[0].type
);
90 EXPECT_EQ(NetLog::SOURCE_NONE
, entries
[0].source
.type
);
91 EXPECT_NE(NetLog::Source::kInvalidId
, entries
[0].source
.id
);
92 EXPECT_EQ(NetLog::PHASE_NONE
, entries
[0].phase
);
93 EXPECT_GE(base::TimeTicks::Now(), entries
[0].time
);
95 int logged_capture_mode
;
97 entries
[0].GetIntegerValue("capture_mode", &logged_capture_mode
));
98 EXPECT_EQ(CaptureModeToInt(mode
), logged_capture_mode
);
104 class CountingObserver
: public NetLog::ThreadSafeObserver
{
106 CountingObserver() : count_(0) {}
108 ~CountingObserver() override
{
110 net_log()->DeprecatedRemoveObserver(this);
113 void OnAddEntry(const NetLog::Entry
& entry
) override
{ ++count_
; }
115 int count() const { return count_
; }
121 class LoggingObserver
: public NetLog::ThreadSafeObserver
{
125 ~LoggingObserver() override
{
127 net_log()->DeprecatedRemoveObserver(this);
130 void OnAddEntry(const NetLog::Entry
& entry
) override
{
131 base::Value
* value
= entry
.ToValue();
132 base::DictionaryValue
* dict
= NULL
;
133 ASSERT_TRUE(value
->GetAsDictionary(&dict
));
134 values_
.push_back(dict
);
137 size_t GetNumValues() const { return values_
.size(); }
138 base::DictionaryValue
* GetValue(size_t index
) const { return values_
[index
]; }
141 ScopedVector
<base::DictionaryValue
> values_
;
144 void AddEvent(NetLog
* net_log
) {
145 net_log
->AddGlobalEntry(NetLog::TYPE_CANCELLED
,
146 base::Bind(CaptureModeToValue
));
149 // A thread that waits until an event has been signalled before calling
151 class NetLogTestThread
: public base::SimpleThread
{
154 : base::SimpleThread("NetLogTest"), net_log_(NULL
), start_event_(NULL
) {}
156 // We'll wait for |start_event| to be triggered before calling a subclass's
157 // subclass's RunTestThread() function.
158 void Init(NetLog
* net_log
, base::WaitableEvent
* start_event
) {
159 start_event_
= start_event
;
163 void Run() override
{
164 start_event_
->Wait();
168 // Subclasses must override this with the code they want to run on their
170 virtual void RunTestThread() = 0;
176 // Only triggered once all threads have been created, to make it less likely
177 // each thread completes before the next one starts.
178 base::WaitableEvent
* start_event_
;
180 DISALLOW_COPY_AND_ASSIGN(NetLogTestThread
);
183 // A thread that adds a bunch of events to the NetLog.
184 class AddEventsTestThread
: public NetLogTestThread
{
186 AddEventsTestThread() {}
187 ~AddEventsTestThread() override
{}
190 void RunTestThread() override
{
191 for (int i
= 0; i
< kEvents
; ++i
)
195 DISALLOW_COPY_AND_ASSIGN(AddEventsTestThread
);
198 // A thread that adds and removes an observer from the NetLog repeatedly.
199 class AddRemoveObserverTestThread
: public NetLogTestThread
{
201 AddRemoveObserverTestThread() {}
203 ~AddRemoveObserverTestThread() override
{ EXPECT_TRUE(!observer_
.net_log()); }
206 void RunTestThread() override
{
207 for (int i
= 0; i
< kEvents
; ++i
) {
208 ASSERT_FALSE(observer_
.net_log());
210 net_log_
->DeprecatedAddObserver(
211 &observer_
, NetLogCaptureMode::IncludeCookiesAndCredentials());
212 ASSERT_EQ(net_log_
, observer_
.net_log());
213 ASSERT_EQ(NetLogCaptureMode::IncludeCookiesAndCredentials(),
214 observer_
.capture_mode());
216 net_log_
->SetObserverCaptureMode(&observer_
,
217 NetLogCaptureMode::IncludeSocketBytes());
218 ASSERT_EQ(net_log_
, observer_
.net_log());
219 ASSERT_EQ(NetLogCaptureMode::IncludeSocketBytes(),
220 observer_
.capture_mode());
222 net_log_
->DeprecatedRemoveObserver(&observer_
);
223 ASSERT_TRUE(!observer_
.net_log());
227 CountingObserver observer_
;
229 DISALLOW_COPY_AND_ASSIGN(AddRemoveObserverTestThread
);
232 // Creates |kThreads| threads of type |ThreadType| and then runs them all
234 template <class ThreadType
>
235 void RunTestThreads(NetLog
* net_log
) {
236 ThreadType threads
[kThreads
];
237 base::WaitableEvent
start_event(true, false);
239 for (size_t i
= 0; i
< arraysize(threads
); ++i
) {
240 threads
[i
].Init(net_log
, &start_event
);
244 start_event
.Signal();
246 for (size_t i
= 0; i
< arraysize(threads
); ++i
)
250 // Makes sure that events on multiple threads are dispatched to all observers.
251 TEST(NetLogTest
, NetLogEventThreads
) {
254 // Attach some observers. Since they're created after |net_log|, they'll
255 // safely detach themselves on destruction.
256 CountingObserver observers
[3];
257 for (size_t i
= 0; i
< arraysize(observers
); ++i
) {
258 net_log
.DeprecatedAddObserver(&observers
[i
],
259 NetLogCaptureMode::IncludeSocketBytes());
262 // Run a bunch of threads to completion, each of which will emit events to
264 RunTestThreads
<AddEventsTestThread
>(&net_log
);
266 // Check that each observer saw the emitted events.
267 const int kTotalEvents
= kThreads
* kEvents
;
268 for (size_t i
= 0; i
< arraysize(observers
); ++i
)
269 EXPECT_EQ(kTotalEvents
, observers
[i
].count());
272 // Test adding and removing a single observer.
273 TEST(NetLogTest
, NetLogAddRemoveObserver
) {
275 CountingObserver observer
;
278 EXPECT_EQ(0, observer
.count());
279 EXPECT_EQ(NULL
, observer
.net_log());
280 EXPECT_FALSE(net_log
.IsCapturing());
282 // Add the observer and add an event.
283 net_log
.DeprecatedAddObserver(
284 &observer
, NetLogCaptureMode::IncludeCookiesAndCredentials());
285 EXPECT_TRUE(net_log
.IsCapturing());
286 EXPECT_EQ(&net_log
, observer
.net_log());
287 EXPECT_EQ(NetLogCaptureMode::IncludeCookiesAndCredentials(),
288 observer
.capture_mode());
289 EXPECT_TRUE(net_log
.IsCapturing());
292 EXPECT_EQ(1, observer
.count());
294 // Change the observer's logging level and add an event.
295 net_log
.SetObserverCaptureMode(&observer
,
296 NetLogCaptureMode::IncludeSocketBytes());
297 EXPECT_EQ(&net_log
, observer
.net_log());
298 EXPECT_EQ(NetLogCaptureMode::IncludeSocketBytes(), observer
.capture_mode());
299 EXPECT_TRUE(net_log
.IsCapturing());
302 EXPECT_EQ(2, observer
.count());
304 // Remove observer and add an event.
305 net_log
.DeprecatedRemoveObserver(&observer
);
306 EXPECT_EQ(NULL
, observer
.net_log());
307 EXPECT_FALSE(net_log
.IsCapturing());
310 EXPECT_EQ(2, observer
.count());
312 // Add the observer a final time, and add an event.
313 net_log
.DeprecatedAddObserver(&observer
,
314 NetLogCaptureMode::IncludeSocketBytes());
315 EXPECT_EQ(&net_log
, observer
.net_log());
316 EXPECT_EQ(NetLogCaptureMode::IncludeSocketBytes(), observer
.capture_mode());
317 EXPECT_TRUE(net_log
.IsCapturing());
320 EXPECT_EQ(3, observer
.count());
323 // Test adding and removing two observers at different log levels.
324 TEST(NetLogTest
, NetLogTwoObservers
) {
326 LoggingObserver observer
[2];
328 // Add first observer.
329 net_log
.DeprecatedAddObserver(
330 &observer
[0], NetLogCaptureMode::IncludeCookiesAndCredentials());
331 EXPECT_EQ(&net_log
, observer
[0].net_log());
332 EXPECT_EQ(NULL
, observer
[1].net_log());
333 EXPECT_EQ(NetLogCaptureMode::IncludeCookiesAndCredentials(),
334 observer
[0].capture_mode());
335 EXPECT_TRUE(net_log
.IsCapturing());
337 // Add second observer observer.
338 net_log
.DeprecatedAddObserver(&observer
[1],
339 NetLogCaptureMode::IncludeSocketBytes());
340 EXPECT_EQ(&net_log
, observer
[0].net_log());
341 EXPECT_EQ(&net_log
, observer
[1].net_log());
342 EXPECT_EQ(NetLogCaptureMode::IncludeCookiesAndCredentials(),
343 observer
[0].capture_mode());
344 EXPECT_EQ(NetLogCaptureMode::IncludeSocketBytes(),
345 observer
[1].capture_mode());
346 EXPECT_TRUE(net_log
.IsCapturing());
348 // Add event and make sure both observers receive it at their respective log
352 ASSERT_EQ(1U, observer
[0].GetNumValues());
353 ASSERT_TRUE(observer
[0].GetValue(0)->GetInteger("params", ¶m
));
354 EXPECT_EQ(CaptureModeToInt(observer
[0].capture_mode()), param
);
355 ASSERT_EQ(1U, observer
[1].GetNumValues());
356 ASSERT_TRUE(observer
[1].GetValue(0)->GetInteger("params", ¶m
));
357 EXPECT_EQ(CaptureModeToInt(observer
[1].capture_mode()), param
);
359 // Remove second observer.
360 net_log
.DeprecatedRemoveObserver(&observer
[1]);
361 EXPECT_EQ(&net_log
, observer
[0].net_log());
362 EXPECT_EQ(NULL
, observer
[1].net_log());
363 EXPECT_EQ(NetLogCaptureMode::IncludeCookiesAndCredentials(),
364 observer
[0].capture_mode());
365 EXPECT_TRUE(net_log
.IsCapturing());
367 // Add event and make sure only second observer gets it.
369 EXPECT_EQ(2U, observer
[0].GetNumValues());
370 EXPECT_EQ(1U, observer
[1].GetNumValues());
372 // Remove first observer.
373 net_log
.DeprecatedRemoveObserver(&observer
[0]);
374 EXPECT_EQ(NULL
, observer
[0].net_log());
375 EXPECT_EQ(NULL
, observer
[1].net_log());
376 EXPECT_FALSE(net_log
.IsCapturing());
378 // Add event and make sure neither observer gets it.
380 EXPECT_EQ(2U, observer
[0].GetNumValues());
381 EXPECT_EQ(1U, observer
[1].GetNumValues());
384 // Makes sure that adding and removing observers simultaneously on different
386 TEST(NetLogTest
, NetLogAddRemoveObserverThreads
) {
389 // Run a bunch of threads to completion, each of which will repeatedly add
390 // and remove an observer, and set its logging level.
391 RunTestThreads
<AddRemoveObserverTestThread
>(&net_log
);