Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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. | |
| 4 | |
| 5 #include "net/base/trace_net_log_observer.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/debug/trace_event.h" | |
| 11 #include "base/debug/trace_event_impl.h" | |
| 12 #include "base/json/json_reader.h" | |
| 13 #include "base/logging.h" | |
| 14 #include "base/memory/ref_counted.h" | |
| 15 #include "base/memory/ref_counted_memory.h" | |
| 16 #include "base/memory/scoped_ptr.h" | |
| 17 #include "base/run_loop.h" | |
| 18 #include "base/strings/stringprintf.h" | |
| 19 #include "base/values.h" | |
| 20 #include "net/base/capturing_net_log.h" | |
| 21 #include "net/base/net_log.h" | |
| 22 #include "testing/gtest/include/gtest/gtest.h" | |
| 23 | |
| 24 using base::debug::TraceLog; | |
| 25 | |
| 26 namespace net { | |
| 27 | |
| 28 namespace { | |
| 29 | |
| 30 struct TraceEntryInfo { | |
| 31 std::string category; | |
| 32 std::string id; | |
| 33 std::string phase; | |
| 34 std::string name; | |
| 35 std::string source_type; | |
| 36 }; | |
| 37 | |
| 38 TraceEntryInfo GetTraceEntryInfoFromValue(const base::DictionaryValue& value) { | |
| 39 TraceEntryInfo info; | |
| 40 value.GetString("cat", &info.category); | |
| 41 value.GetString("id", &info.id); | |
| 42 value.GetString("ph", &info.phase); | |
| 43 value.GetString("name", &info.name); | |
| 44 value.GetString("args.source_type", &info.source_type); | |
|
mmenke
2014/09/08 16:02:04
These should all be wrapped in EXPECT_TRUE
xunjieli
2014/09/08 19:47:45
Done.
| |
| 45 | |
| 46 return info; | |
| 47 } | |
| 48 | |
| 49 class TraceNetLogObserverTest : public testing::Test { | |
| 50 public: | |
| 51 TraceNetLogObserverTest() { | |
| 52 TraceLog::DeleteForTesting(); | |
| 53 TraceLog* tracelog = TraceLog::GetInstance(); | |
| 54 DCHECK(tracelog); | |
| 55 DCHECK(!tracelog->IsEnabled()); | |
| 56 trace_buffer_.SetOutputCallback(json_output_.GetCallback()); | |
| 57 trace_net_log_observer_.reset(new TraceNetLogObserver()); | |
| 58 trace_events_.reset(new base::ListValue()); | |
| 59 } | |
| 60 | |
| 61 virtual ~TraceNetLogObserverTest() { | |
| 62 DCHECK(!TraceLog::GetInstance()->IsEnabled()); | |
| 63 TraceLog::DeleteForTesting(); | |
| 64 } | |
| 65 | |
| 66 void OnTraceDataCollected( | |
| 67 base::RunLoop* run_loop, | |
| 68 const scoped_refptr<base::RefCountedString>& events_str, | |
| 69 bool has_more_events) { | |
| 70 DCHECK(trace_events_->empty()); | |
| 71 trace_buffer_.Start(); | |
| 72 trace_buffer_.AddFragment(events_str->data()); | |
| 73 trace_buffer_.Finish(); | |
| 74 | |
| 75 scoped_ptr<base::Value> trace_value; | |
| 76 trace_value.reset(base::JSONReader::Read( | |
| 77 json_output_.json_output, | |
| 78 base::JSON_PARSE_RFC | base::JSON_DETACHABLE_CHILDREN)); | |
| 79 | |
| 80 ASSERT_TRUE(trace_value) << json_output_.json_output; | |
| 81 base::ListValue* trace_events = NULL; | |
| 82 ASSERT_TRUE(trace_value->GetAsList(&trace_events)); | |
| 83 | |
| 84 trace_events_ = FilterNetLogTraceEvents(*trace_events); | |
| 85 | |
| 86 if (!has_more_events) | |
| 87 run_loop->Quit(); | |
| 88 } | |
| 89 | |
| 90 static void EnableTraceLog() { | |
| 91 TraceLog::GetInstance()->SetEnabled( | |
| 92 base::debug::CategoryFilter("netlog"), | |
| 93 TraceLog::RECORDING_MODE, | |
| 94 base::debug::TraceOptions()); | |
| 95 } | |
| 96 | |
| 97 void EndTraceAndFlush() { | |
| 98 base::RunLoop run_loop; | |
| 99 TraceLog::GetInstance()->SetDisabled(); | |
| 100 TraceLog::GetInstance()->Flush( | |
| 101 base::Bind(&TraceNetLogObserverTest::OnTraceDataCollected, | |
| 102 base::Unretained(this), | |
| 103 base::Unretained(&run_loop))); | |
| 104 run_loop.Run(); | |
| 105 } | |
| 106 | |
| 107 void set_trace_net_log_observer(TraceNetLogObserver* trace_net_log_observer) { | |
| 108 trace_net_log_observer_.reset(trace_net_log_observer); | |
| 109 } | |
| 110 | |
| 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"; | |
| 118 continue; | |
| 119 } | |
| 120 std::string category; | |
| 121 if (!dict->GetString("cat", &category)) { | |
| 122 ADD_FAILURE() << | |
| 123 "Unexpected item without a category field in trace_events"; | |
| 124 continue; | |
| 125 } | |
| 126 if (category != "netlog") | |
| 127 continue; | |
| 128 filtered_trace_events->Append(dict->DeepCopy()); | |
| 129 } | |
| 130 return filtered_trace_events.Pass(); | |
| 131 } | |
| 132 | |
| 133 base::ListValue* trace_events() const { | |
| 134 return trace_events_.get(); | |
| 135 } | |
| 136 | |
| 137 CapturingNetLog* net_log() { | |
| 138 return &net_log_; | |
| 139 } | |
| 140 | |
| 141 TraceNetLogObserver* trace_net_log_observer() const { | |
| 142 return trace_net_log_observer_.get(); | |
| 143 } | |
| 144 | |
| 145 private: | |
| 146 scoped_ptr<base::ListValue> trace_events_; | |
| 147 base::debug::TraceResultBuffer trace_buffer_; | |
| 148 base::debug::TraceResultBuffer::SimpleOutput json_output_; | |
| 149 CapturingNetLog net_log_; | |
| 150 scoped_ptr<TraceNetLogObserver> trace_net_log_observer_; | |
| 151 }; | |
| 152 | |
| 153 TEST_F(TraceNetLogObserverTest, TracingNotEnabled) { | |
| 154 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
| 155 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
| 156 | |
| 157 EndTraceAndFlush(); | |
| 158 trace_net_log_observer()->StopWatchForTraceStart(); | |
| 159 | |
| 160 ASSERT_EQ(0u, trace_events()->GetSize()); | |
| 161 } | |
| 162 | |
| 163 TEST_F(TraceNetLogObserverTest, TraceEventCaptured) { | |
| 164 CapturingNetLog::CapturedEntryList entries; | |
| 165 net_log()->GetEntries(&entries); | |
| 166 ASSERT_TRUE(entries.empty()); | |
| 167 | |
| 168 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
| 169 EnableTraceLog(); | |
| 170 BoundNetLog bound_net_log = BoundNetLog::Make(net_log(), | |
| 171 net::NetLog::SOURCE_NONE); | |
| 172 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
| 173 bound_net_log.BeginEvent(NetLog::TYPE_URL_REQUEST_START_JOB); | |
| 174 bound_net_log.EndEvent(NetLog::TYPE_REQUEST_ALIVE); | |
| 175 | |
| 176 net_log()->GetEntries(&entries); | |
| 177 ASSERT_EQ(3u, entries.size()); | |
| 178 EndTraceAndFlush(); | |
| 179 trace_net_log_observer()->StopWatchForTraceStart(); | |
| 180 ASSERT_EQ(3u, trace_events()->GetSize()); | |
| 181 const base::DictionaryValue* item1 = NULL; | |
| 182 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); | |
| 183 const base::DictionaryValue* item2 = NULL; | |
| 184 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); | |
| 185 const base::DictionaryValue* item3 = NULL; | |
| 186 ASSERT_TRUE(trace_events()->GetDictionary(2, &item3)); | |
| 187 | |
| 188 TraceEntryInfo expected_item1 = TraceEntryInfo{ | |
| 189 "netlog", | |
| 190 base::StringPrintf("0x%d", entries[0].source.id), | |
| 191 std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | |
| 192 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), | |
| 193 NetLog::SourceTypeToString(entries[0].source.type)}; | |
| 194 TraceEntryInfo expected_item2 = TraceEntryInfo{ | |
| 195 "netlog", | |
| 196 base::StringPrintf("0x%d", entries[1].source.id), | |
| 197 std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN), | |
| 198 NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB), | |
| 199 NetLog::SourceTypeToString(entries[1].source.type)}; | |
| 200 TraceEntryInfo expected_item3 = TraceEntryInfo{ | |
| 201 "netlog", | |
| 202 base::StringPrintf("0x%d", entries[2].source.id), | |
| 203 std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END), | |
| 204 NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE), | |
| 205 NetLog::SourceTypeToString(entries[2].source.type)}; | |
|
mmenke
2014/09/08 16:02:04
Sorry, I wasn't clear - I mean expected_item1 / ex
xunjieli
2014/09/08 19:47:45
Done.
| |
| 206 | |
| 207 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); | |
| 208 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); | |
| 209 TraceEntryInfo actual_item3 = GetTraceEntryInfoFromValue(*item3); | |
| 210 ASSERT_EQ(expected_item1.category, actual_item1.category); | |
| 211 ASSERT_EQ(expected_item1.id, actual_item1.id); | |
| 212 ASSERT_EQ(expected_item1.phase, actual_item1.phase); | |
| 213 ASSERT_EQ(expected_item1.name, actual_item1.name); | |
| 214 ASSERT_EQ(expected_item1.source_type, actual_item1.source_type); | |
| 215 | |
| 216 ASSERT_EQ(expected_item2.category, actual_item2.category); | |
| 217 ASSERT_EQ(expected_item2.id, actual_item2.id); | |
| 218 ASSERT_EQ(expected_item2.phase, actual_item2.phase); | |
| 219 ASSERT_EQ(expected_item2.name, actual_item2.name); | |
| 220 ASSERT_EQ(expected_item2.source_type, actual_item2.source_type); | |
| 221 | |
| 222 ASSERT_EQ(expected_item3.category, actual_item3.category); | |
| 223 ASSERT_EQ(expected_item3.id, actual_item3.id); | |
| 224 ASSERT_EQ(expected_item3.phase, actual_item3.phase); | |
| 225 ASSERT_EQ(expected_item3.name, actual_item3.name); | |
| 226 ASSERT_EQ(expected_item3.source_type, actual_item3.source_type); | |
|
mmenke
2014/09/08 16:02:04
All of these can be EXPECTs. The size checks coul
xunjieli
2014/09/08 19:47:45
Done. I see. Thanks for letting me know the distin
| |
| 227 } | |
| 228 | |
| 229 TEST_F(TraceNetLogObserverTest, EnableAndDisableTracing) { | |
| 230 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
| 231 EnableTraceLog(); | |
| 232 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
| 233 TraceLog::GetInstance()->SetDisabled(); | |
| 234 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
| 235 EnableTraceLog(); | |
| 236 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
| 237 | |
| 238 EndTraceAndFlush(); | |
| 239 trace_net_log_observer()->StopWatchForTraceStart(); | |
| 240 | |
| 241 CapturingNetLog::CapturedEntryList entries; | |
| 242 net_log()->GetEntries(&entries); | |
| 243 ASSERT_EQ(3u, entries.size()); | |
| 244 ASSERT_EQ(2u, trace_events()->GetSize()); | |
| 245 const base::DictionaryValue* item1 = NULL; | |
| 246 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); | |
| 247 const base::DictionaryValue* item2 = NULL; | |
| 248 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); | |
| 249 | |
| 250 TraceEntryInfo expected_item1 = TraceEntryInfo{ | |
| 251 "netlog", | |
| 252 base::StringPrintf("0x%d", entries[0].source.id), | |
| 253 std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | |
| 254 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), | |
| 255 NetLog::SourceTypeToString(entries[0].source.type)}; | |
| 256 TraceEntryInfo expected_item2 = TraceEntryInfo{ | |
| 257 "netlog", | |
| 258 base::StringPrintf("0x%d", entries[2].source.id), | |
| 259 std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | |
| 260 NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB), | |
| 261 NetLog::SourceTypeToString(entries[2].source.type)}; | |
| 262 | |
| 263 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); | |
| 264 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); | |
| 265 ASSERT_EQ(expected_item1.category, actual_item1.category); | |
| 266 ASSERT_EQ(expected_item1.id, actual_item1.id); | |
| 267 ASSERT_EQ(expected_item1.phase, actual_item1.phase); | |
| 268 ASSERT_EQ(expected_item1.name, actual_item1.name); | |
| 269 ASSERT_EQ(expected_item1.source_type, actual_item1.source_type); | |
| 270 | |
| 271 ASSERT_EQ(expected_item2.category, actual_item2.category); | |
| 272 ASSERT_EQ(expected_item2.id, actual_item2.id); | |
| 273 ASSERT_EQ(expected_item2.phase, actual_item2.phase); | |
| 274 ASSERT_EQ(expected_item2.name, actual_item2.name); | |
| 275 ASSERT_EQ(expected_item2.source_type, actual_item2.source_type); | |
| 276 } | |
| 277 | |
| 278 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileTracing) { | |
| 279 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
| 280 EnableTraceLog(); | |
| 281 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
| 282 trace_net_log_observer()->StopWatchForTraceStart(); | |
| 283 set_trace_net_log_observer(NULL); | |
| 284 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
| 285 | |
| 286 EndTraceAndFlush(); | |
| 287 | |
| 288 CapturingNetLog::CapturedEntryList entries; | |
| 289 net_log()->GetEntries(&entries); | |
| 290 ASSERT_EQ(2u, entries.size()); | |
| 291 ASSERT_EQ(1u, trace_events()->GetSize()); | |
| 292 | |
| 293 const base::DictionaryValue* item1 = NULL; | |
| 294 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); | |
| 295 | |
| 296 TraceEntryInfo expected_item1 = TraceEntryInfo{ | |
| 297 "netlog", | |
| 298 base::StringPrintf("0x%d", entries[0].source.id), | |
| 299 std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | |
| 300 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), | |
| 301 NetLog::SourceTypeToString(entries[0].source.type)}; | |
| 302 | |
| 303 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); | |
| 304 ASSERT_EQ(expected_item1.category, actual_item1.category); | |
| 305 ASSERT_EQ(expected_item1.id, actual_item1.id); | |
| 306 ASSERT_EQ(expected_item1.phase, actual_item1.phase); | |
| 307 ASSERT_EQ(expected_item1.name, actual_item1.name); | |
| 308 ASSERT_EQ(expected_item1.source_type, actual_item1.source_type); | |
| 309 } | |
| 310 | |
| 311 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileNotTracing) { | |
| 312 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
| 313 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
| 314 trace_net_log_observer()->StopWatchForTraceStart(); | |
| 315 set_trace_net_log_observer(NULL); | |
| 316 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
| 317 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
| 318 | |
| 319 EndTraceAndFlush(); | |
| 320 | |
| 321 CapturingNetLog::CapturedEntryList entries; | |
| 322 net_log()->GetEntries(&entries); | |
| 323 ASSERT_EQ(3u, entries.size()); | |
| 324 ASSERT_EQ(0u, trace_events()->GetSize()); | |
| 325 } | |
| 326 | |
| 327 TEST_F(TraceNetLogObserverTest, CreateObserverAfterTracingStarts) { | |
| 328 set_trace_net_log_observer(NULL); | |
| 329 EnableTraceLog(); | |
| 330 set_trace_net_log_observer(new TraceNetLogObserver()); | |
| 331 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
| 332 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
| 333 trace_net_log_observer()->StopWatchForTraceStart(); | |
| 334 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
| 335 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
| 336 | |
| 337 EndTraceAndFlush(); | |
| 338 | |
| 339 CapturingNetLog::CapturedEntryList entries; | |
| 340 net_log()->GetEntries(&entries); | |
| 341 ASSERT_EQ(3u, entries.size()); | |
| 342 ASSERT_EQ(0u, trace_events()->GetSize()); | |
| 343 } | |
| 344 | |
| 345 TEST_F(TraceNetLogObserverTest, EventsWithAndWithoutParameters) { | |
| 346 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
| 347 EnableTraceLog(); | |
| 348 NetLog::ParametersCallback net_log_callback; | |
| 349 std::string param = "bar"; | |
| 350 net_log_callback = NetLog::StringCallback("foo", | |
| 351 ¶m); | |
| 352 | |
| 353 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED, net_log_callback); | |
| 354 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
| 355 | |
| 356 EndTraceAndFlush(); | |
| 357 trace_net_log_observer()->StopWatchForTraceStart(); | |
| 358 | |
| 359 CapturingNetLog::CapturedEntryList entries; | |
| 360 net_log()->GetEntries(&entries); | |
| 361 ASSERT_EQ(2u, entries.size()); | |
| 362 ASSERT_EQ(2u, trace_events()->GetSize()); | |
| 363 const base::DictionaryValue* item1 = NULL; | |
| 364 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); | |
| 365 const base::DictionaryValue* item2 = NULL; | |
| 366 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); | |
| 367 | |
| 368 TraceEntryInfo expected_item1 = TraceEntryInfo{ | |
| 369 "netlog", | |
| 370 base::StringPrintf("0x%d", entries[0].source.id), | |
| 371 std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | |
| 372 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), | |
| 373 NetLog::SourceTypeToString(entries[0].source.type)}; | |
| 374 TraceEntryInfo expected_item2 = TraceEntryInfo{ | |
| 375 "netlog", | |
| 376 base::StringPrintf("0x%d", entries[1].source.id), | |
| 377 std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | |
| 378 NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE), | |
| 379 NetLog::SourceTypeToString(entries[1].source.type)}; | |
| 380 | |
| 381 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); | |
| 382 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); | |
| 383 ASSERT_EQ(expected_item1.category, actual_item1.category); | |
| 384 ASSERT_EQ(expected_item1.id, actual_item1.id); | |
| 385 ASSERT_EQ(expected_item1.phase, actual_item1.phase); | |
| 386 ASSERT_EQ(expected_item1.name, actual_item1.name); | |
| 387 ASSERT_EQ(expected_item1.source_type, actual_item1.source_type); | |
| 388 | |
| 389 ASSERT_EQ(expected_item2.category, actual_item2.category); | |
| 390 ASSERT_EQ(expected_item2.id, actual_item2.id); | |
| 391 ASSERT_EQ(expected_item2.phase, actual_item2.phase); | |
| 392 ASSERT_EQ(expected_item2.name, actual_item2.name); | |
| 393 ASSERT_EQ(expected_item2.source_type, actual_item2.source_type); | |
| 394 | |
| 395 std::string item1_params; | |
| 396 std::string item2_params; | |
| 397 ASSERT_TRUE(item1->GetString("args.params.foo", &item1_params)); | |
| 398 ASSERT_EQ("bar", item1_params); | |
| 399 | |
| 400 ASSERT_TRUE(item2->GetString("args.params", &item2_params)); | |
| 401 ASSERT_TRUE(item2_params.empty()); | |
| 402 } | |
| 403 | |
| 404 } // namespace | |
| 405 | |
| 406 } // namespace net | |
| OLD | NEW |