1 // Copyright 2014 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/trace_net_log_observer.h"
10 #include "base/json/json_reader.h"
11 #include "base/logging.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/ref_counted_memory.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/run_loop.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/trace_event/trace_event.h"
18 #include "base/trace_event/trace_event_impl.h"
19 #include "base/values.h"
20 #include "net/log/net_log.h"
21 #include "net/log/test_net_log.h"
22 #include "net/log/test_net_log_entry.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using base::trace_event::TraceLog
;
31 // TraceLog category for NetLog events.
32 const char kNetLogTracingCategory
[] = "netlog";
34 struct TraceEntryInfo
{
39 std::string source_type
;
42 TraceEntryInfo
GetTraceEntryInfoFromValue(const base::DictionaryValue
& value
) {
44 EXPECT_TRUE(value
.GetString("cat", &info
.category
));
45 EXPECT_TRUE(value
.GetString("id", &info
.id
));
46 EXPECT_TRUE(value
.GetString("ph", &info
.phase
));
47 EXPECT_TRUE(value
.GetString("name", &info
.name
));
48 EXPECT_TRUE(value
.GetString("args.source_type", &info
.source_type
));
53 class TraceNetLogObserverTest
: public testing::Test
{
55 TraceNetLogObserverTest() {
56 TraceLog
* tracelog
= TraceLog::GetInstance();
58 DCHECK(!tracelog
->IsEnabled());
59 trace_buffer_
.SetOutputCallback(json_output_
.GetCallback());
60 trace_net_log_observer_
.reset(new TraceNetLogObserver());
61 trace_events_
.reset(new base::ListValue());
64 ~TraceNetLogObserverTest() override
{
65 DCHECK(!TraceLog::GetInstance()->IsEnabled());
68 void OnTraceDataCollected(
69 base::RunLoop
* run_loop
,
70 const scoped_refptr
<base::RefCountedString
>& events_str
,
71 bool has_more_events
) {
72 DCHECK(trace_events_
->empty());
73 trace_buffer_
.Start();
74 trace_buffer_
.AddFragment(events_str
->data());
75 trace_buffer_
.Finish();
77 scoped_ptr
<base::Value
> trace_value
;
78 trace_value
.reset(base::JSONReader::DeprecatedRead(
79 json_output_
.json_output
,
80 base::JSON_PARSE_RFC
| base::JSON_DETACHABLE_CHILDREN
));
82 ASSERT_TRUE(trace_value
) << json_output_
.json_output
;
83 base::ListValue
* trace_events
= NULL
;
84 ASSERT_TRUE(trace_value
->GetAsList(&trace_events
));
86 trace_events_
= FilterNetLogTraceEvents(*trace_events
);
92 static void EnableTraceLog() {
93 TraceLog::GetInstance()->SetEnabled(
94 base::trace_event::TraceConfig(kNetLogTracingCategory
, ""),
95 TraceLog::RECORDING_MODE
);
98 void EndTraceAndFlush() {
99 base::RunLoop run_loop
;
100 TraceLog::GetInstance()->SetDisabled();
101 TraceLog::GetInstance()->Flush(
102 base::Bind(&TraceNetLogObserverTest::OnTraceDataCollected
,
103 base::Unretained(this), base::Unretained(&run_loop
)));
107 void set_trace_net_log_observer(TraceNetLogObserver
* trace_net_log_observer
) {
108 trace_net_log_observer_
.reset(trace_net_log_observer
);
111 static scoped_ptr
<base::ListValue
> FilterNetLogTraceEvents(
112 const base::ListValue
& trace_events
) {
113 scoped_ptr
<base::ListValue
> filtered_trace_events(new base::ListValue());
114 for (size_t i
= 0; i
< trace_events
.GetSize(); i
++) {
115 const base::DictionaryValue
* dict
= NULL
;
116 if (!trace_events
.GetDictionary(i
, &dict
)) {
117 ADD_FAILURE() << "Unexpected non-dictionary event in trace_events";
120 std::string category
;
121 if (!dict
->GetString("cat", &category
)) {
123 << "Unexpected item without a category field in trace_events";
126 if (category
!= kNetLogTracingCategory
)
128 filtered_trace_events
->Append(dict
->DeepCopy());
130 return filtered_trace_events
.Pass();
133 base::ListValue
* trace_events() const { return trace_events_
.get(); }
135 TestNetLog
* net_log() { return &net_log_
; }
137 TraceNetLogObserver
* trace_net_log_observer() const {
138 return trace_net_log_observer_
.get();
142 scoped_ptr
<base::ListValue
> trace_events_
;
143 base::trace_event::TraceResultBuffer trace_buffer_
;
144 base::trace_event::TraceResultBuffer::SimpleOutput json_output_
;
146 scoped_ptr
<TraceNetLogObserver
> trace_net_log_observer_
;
149 TEST_F(TraceNetLogObserverTest
, TracingNotEnabled
) {
150 trace_net_log_observer()->WatchForTraceStart(net_log());
151 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE
);
154 trace_net_log_observer()->StopWatchForTraceStart();
156 EXPECT_EQ(0u, trace_events()->GetSize());
159 TEST_F(TraceNetLogObserverTest
, TraceEventCaptured
) {
160 TestNetLogEntry::List entries
;
161 net_log()->GetEntries(&entries
);
162 EXPECT_TRUE(entries
.empty());
164 trace_net_log_observer()->WatchForTraceStart(net_log());
166 BoundNetLog bound_net_log
=
167 BoundNetLog::Make(net_log(), net::NetLog::SOURCE_NONE
);
168 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED
);
169 bound_net_log
.BeginEvent(NetLog::TYPE_URL_REQUEST_START_JOB
);
170 bound_net_log
.EndEvent(NetLog::TYPE_REQUEST_ALIVE
);
172 net_log()->GetEntries(&entries
);
173 EXPECT_EQ(3u, entries
.size());
175 trace_net_log_observer()->StopWatchForTraceStart();
176 EXPECT_EQ(3u, trace_events()->GetSize());
177 const base::DictionaryValue
* item1
= NULL
;
178 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1
));
179 const base::DictionaryValue
* item2
= NULL
;
180 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2
));
181 const base::DictionaryValue
* item3
= NULL
;
182 ASSERT_TRUE(trace_events()->GetDictionary(2, &item3
));
184 TraceEntryInfo actual_item1
= GetTraceEntryInfoFromValue(*item1
);
185 TraceEntryInfo actual_item2
= GetTraceEntryInfoFromValue(*item2
);
186 TraceEntryInfo actual_item3
= GetTraceEntryInfoFromValue(*item3
);
187 EXPECT_EQ(kNetLogTracingCategory
, actual_item1
.category
);
188 EXPECT_EQ(base::StringPrintf("0x%d", entries
[0].source
.id
), actual_item1
.id
);
189 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
),
191 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED
),
193 EXPECT_EQ(NetLog::SourceTypeToString(entries
[0].source
.type
),
194 actual_item1
.source_type
);
196 EXPECT_EQ(kNetLogTracingCategory
, actual_item2
.category
);
197 EXPECT_EQ(base::StringPrintf("0x%d", entries
[1].source
.id
), actual_item2
.id
);
198 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN
),
200 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB
),
202 EXPECT_EQ(NetLog::SourceTypeToString(entries
[1].source
.type
),
203 actual_item2
.source_type
);
205 EXPECT_EQ(kNetLogTracingCategory
, actual_item3
.category
);
206 EXPECT_EQ(base::StringPrintf("0x%d", entries
[2].source
.id
), actual_item3
.id
);
207 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END
),
209 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE
),
211 EXPECT_EQ(NetLog::SourceTypeToString(entries
[2].source
.type
),
212 actual_item3
.source_type
);
215 TEST_F(TraceNetLogObserverTest
, EnableAndDisableTracing
) {
216 trace_net_log_observer()->WatchForTraceStart(net_log());
218 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED
);
219 TraceLog::GetInstance()->SetDisabled();
220 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE
);
222 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB
);
225 trace_net_log_observer()->StopWatchForTraceStart();
227 TestNetLogEntry::List entries
;
228 net_log()->GetEntries(&entries
);
229 EXPECT_EQ(3u, entries
.size());
230 EXPECT_EQ(2u, trace_events()->GetSize());
231 const base::DictionaryValue
* item1
= NULL
;
232 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1
));
233 const base::DictionaryValue
* item2
= NULL
;
234 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2
));
236 TraceEntryInfo actual_item1
= GetTraceEntryInfoFromValue(*item1
);
237 TraceEntryInfo actual_item2
= GetTraceEntryInfoFromValue(*item2
);
238 EXPECT_EQ(kNetLogTracingCategory
, actual_item1
.category
);
239 EXPECT_EQ(base::StringPrintf("0x%d", entries
[0].source
.id
), actual_item1
.id
);
240 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
),
242 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED
),
244 EXPECT_EQ(NetLog::SourceTypeToString(entries
[0].source
.type
),
245 actual_item1
.source_type
);
247 EXPECT_EQ(kNetLogTracingCategory
, actual_item2
.category
);
248 EXPECT_EQ(base::StringPrintf("0x%d", entries
[2].source
.id
), actual_item2
.id
);
249 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
),
251 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB
),
253 EXPECT_EQ(NetLog::SourceTypeToString(entries
[2].source
.type
),
254 actual_item2
.source_type
);
257 TEST_F(TraceNetLogObserverTest
, DestroyObserverWhileTracing
) {
258 trace_net_log_observer()->WatchForTraceStart(net_log());
260 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED
);
261 trace_net_log_observer()->StopWatchForTraceStart();
262 set_trace_net_log_observer(NULL
);
263 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE
);
267 TestNetLogEntry::List entries
;
268 net_log()->GetEntries(&entries
);
269 EXPECT_EQ(2u, entries
.size());
270 EXPECT_EQ(1u, trace_events()->GetSize());
272 const base::DictionaryValue
* item1
= NULL
;
273 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1
));
275 TraceEntryInfo actual_item1
= GetTraceEntryInfoFromValue(*item1
);
276 EXPECT_EQ(kNetLogTracingCategory
, actual_item1
.category
);
277 EXPECT_EQ(base::StringPrintf("0x%d", entries
[0].source
.id
), actual_item1
.id
);
278 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
),
280 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED
),
282 EXPECT_EQ(NetLog::SourceTypeToString(entries
[0].source
.type
),
283 actual_item1
.source_type
);
286 TEST_F(TraceNetLogObserverTest
, DestroyObserverWhileNotTracing
) {
287 trace_net_log_observer()->WatchForTraceStart(net_log());
288 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED
);
289 trace_net_log_observer()->StopWatchForTraceStart();
290 set_trace_net_log_observer(NULL
);
291 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE
);
292 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB
);
296 TestNetLogEntry::List entries
;
297 net_log()->GetEntries(&entries
);
298 EXPECT_EQ(3u, entries
.size());
299 EXPECT_EQ(0u, trace_events()->GetSize());
302 TEST_F(TraceNetLogObserverTest
, CreateObserverAfterTracingStarts
) {
303 set_trace_net_log_observer(NULL
);
305 set_trace_net_log_observer(new TraceNetLogObserver());
306 trace_net_log_observer()->WatchForTraceStart(net_log());
307 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED
);
308 trace_net_log_observer()->StopWatchForTraceStart();
309 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE
);
310 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB
);
314 TestNetLogEntry::List entries
;
315 net_log()->GetEntries(&entries
);
316 EXPECT_EQ(3u, entries
.size());
317 EXPECT_EQ(0u, trace_events()->GetSize());
320 TEST_F(TraceNetLogObserverTest
, EventsWithAndWithoutParameters
) {
321 trace_net_log_observer()->WatchForTraceStart(net_log());
323 NetLog::ParametersCallback net_log_callback
;
324 std::string param
= "bar";
325 net_log_callback
= NetLog::StringCallback("foo", ¶m
);
327 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED
, net_log_callback
);
328 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE
);
331 trace_net_log_observer()->StopWatchForTraceStart();
333 TestNetLogEntry::List entries
;
334 net_log()->GetEntries(&entries
);
335 EXPECT_EQ(2u, entries
.size());
336 EXPECT_EQ(2u, trace_events()->GetSize());
337 const base::DictionaryValue
* item1
= NULL
;
338 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1
));
339 const base::DictionaryValue
* item2
= NULL
;
340 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2
));
342 TraceEntryInfo actual_item1
= GetTraceEntryInfoFromValue(*item1
);
343 TraceEntryInfo actual_item2
= GetTraceEntryInfoFromValue(*item2
);
344 EXPECT_EQ(kNetLogTracingCategory
, actual_item1
.category
);
345 EXPECT_EQ(base::StringPrintf("0x%d", entries
[0].source
.id
), actual_item1
.id
);
346 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
),
348 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED
),
350 EXPECT_EQ(NetLog::SourceTypeToString(entries
[0].source
.type
),
351 actual_item1
.source_type
);
353 EXPECT_EQ(kNetLogTracingCategory
, actual_item2
.category
);
354 EXPECT_EQ(base::StringPrintf("0x%d", entries
[1].source
.id
), actual_item2
.id
);
355 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
),
357 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE
),
359 EXPECT_EQ(NetLog::SourceTypeToString(entries
[1].source
.type
),
360 actual_item2
.source_type
);
362 std::string item1_params
;
363 std::string item2_params
;
364 EXPECT_TRUE(item1
->GetString("args.params.foo", &item1_params
));
365 EXPECT_EQ("bar", item1_params
);
367 EXPECT_TRUE(item2
->GetString("args.params", &item2_params
));
368 EXPECT_TRUE(item2_params
.empty());