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/strings/stringprintf.h" | |
18 #include "base/values.h" | |
19 #include "net/base/capturing_net_log.h" | |
20 #include "net/base/net_log.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 namespace net { | |
24 | |
25 namespace { | |
26 | |
27 using base::debug::TraceLog; | |
28 | |
29 class TraceNetLogObserverTest : public testing::Test { | |
30 public: | |
31 virtual void SetUp() OVERRIDE { | |
mmenke
2014/08/27 19:03:15
Can we just make these into the constructor and de
xunjieli
2014/09/02 16:37:33
Done.
| |
32 TraceLog::DeleteForTesting(); | |
33 TraceLog* tracelog = TraceLog::GetInstance(); | |
34 ASSERT_TRUE(tracelog); | |
35 ASSERT_FALSE(tracelog->IsEnabled()); | |
36 trace_buffer_.SetOutputCallback(json_output_.GetCallback()); | |
37 net_log_.reset(new CapturingNetLog); | |
38 trace_net_log_observer_.reset(new TraceNetLogObserver()); | |
39 // TODO(xunjieli): Remove this once Trace bug is fixed. | |
40 TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop(); | |
41 } | |
42 | |
43 virtual void TearDown() OVERRIDE { | |
44 EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled()); | |
45 TraceLog::DeleteForTesting(); | |
46 } | |
47 | |
48 void OnTraceDataCollected( | |
49 const scoped_refptr<base::RefCountedString>& events_str, | |
50 bool has_more_events) { | |
51 DCHECK(trace_events_.empty()); | |
52 trace_buffer_.Start(); | |
53 trace_buffer_.AddFragment(events_str->data()); | |
54 trace_buffer_.Finish(); | |
55 | |
56 scoped_ptr<base::Value> trace_value; | |
57 trace_value.reset(base::JSONReader::Read( | |
58 json_output_.json_output, | |
59 base::JSON_PARSE_RFC | base::JSON_DETACHABLE_CHILDREN)); | |
60 | |
61 ASSERT_TRUE(trace_value) << json_output_.json_output; | |
62 base::ListValue* trace_events = NULL; | |
63 ASSERT_TRUE(trace_value.get()); | |
mmenke
2014/08/27 19:03:15
This is redundant with the one above (minor nit:
xunjieli
2014/09/02 16:37:34
Done. I see. Thanks!
| |
64 ASSERT_TRUE(trace_value->GetAsList(&trace_events)); | |
65 trace_events_.Swap(trace_events); | |
66 } | |
67 | |
68 static void EnableTraceLog() { | |
69 TraceLog::GetInstance()->SetEnabled( | |
70 base::debug::CategoryFilter("*"), | |
mmenke
2014/08/27 19:03:15
Could we just filter on "netlog", and then know th
xunjieli
2014/09/02 16:37:33
Done.
| |
71 TraceLog::RECORDING_MODE, | |
72 base::debug::TraceOptions()); | |
73 } | |
74 | |
75 static void DisableTraceLog() { | |
76 TraceLog::GetInstance()->SetDisabled(); | |
77 } | |
78 | |
79 void EndTraceAndFlush() { | |
80 TraceLog::GetInstance()->SetDisabled(); | |
81 TraceLog::GetInstance()->Flush( | |
82 Bind(&TraceNetLogObserverTest::OnTraceDataCollected, | |
83 base::Unretained(this))); | |
84 } | |
85 | |
86 void ResetTraceNetLogObserver(TraceNetLogObserver* trace_net_log_observer) { | |
mmenke
2014/08/27 19:03:14
nit: More common to call methods that do this "se
xunjieli
2014/09/02 16:37:33
Done.
| |
87 trace_net_log_observer_.reset(trace_net_log_observer); | |
88 } | |
89 | |
90 const base::DictionaryValue* FindTraceEntry(NetLog::EventType event_type, | |
91 size_t& pos) { | |
mmenke
2014/08/27 19:03:15
Passing in non-const references violates the style
xunjieli
2014/09/02 16:37:34
Done. Got it. Thanks!
| |
92 // Scan all items | |
mmenke
2014/08/27 19:03:15
nit: Comments should be sentences, and end with p
xunjieli
2014/09/02 16:37:34
Acknowledged. I changed the category filter, as yo
| |
93 std::string type(NetLog::EventTypeToString(event_type)); | |
94 size_t trace_events_count = trace_events_.GetSize(); | |
95 for (size_t i = 0; i < trace_events_count; i++) { | |
96 const base::Value* value = NULL; | |
97 trace_events_.Get(i, &value); | |
98 const base::DictionaryValue* dict = NULL; | |
99 if (!value->GetAsDictionary(&dict)) | |
100 continue; | |
101 std::string actual_type; | |
102 if (dict->GetString("name", &actual_type)) { | |
103 if (actual_type == type) { | |
104 pos = i; | |
105 return dict; | |
106 } | |
107 } | |
108 } | |
109 return NULL; | |
110 } | |
111 | |
112 std::vector<const base::DictionaryValue*> FindTraceEntries( | |
113 NetLog::EventType event_type) { | |
114 std::vector<const base::DictionaryValue*> hits; | |
115 std::string type(NetLog::EventTypeToString(event_type)); | |
116 size_t trace_events_count = trace_events_.GetSize(); | |
117 for (size_t i = 0; i < trace_events_count; i++) { | |
118 const base::Value* value = NULL; | |
119 trace_events_.Get(i, &value); | |
120 const base::DictionaryValue* dict = NULL; | |
121 if (!value->GetAsDictionary(&dict)) | |
122 continue; | |
123 std::string actual_type; | |
124 if (dict->GetString("name", &actual_type)) { | |
125 if (actual_type == type) | |
126 hits.push_back(dict); | |
127 } | |
128 } | |
129 return hits; | |
130 } | |
131 | |
132 CapturingNetLog* net_log() const { | |
133 return net_log_.get(); | |
134 } | |
135 | |
136 TraceNetLogObserver* trace_net_log_observer() const { | |
137 return trace_net_log_observer_.get(); | |
138 } | |
139 | |
140 private: | |
141 base::ListValue trace_events_; | |
142 base::debug::TraceResultBuffer trace_buffer_; | |
143 base::debug::TraceResultBuffer::SimpleOutput json_output_; | |
144 scoped_ptr<CapturingNetLog> net_log_; | |
mmenke
2014/08/27 19:03:15
nit: I don't think this need to be a scoped_ptr.
xunjieli
2014/09/02 16:37:33
But there is a DISALLOW_COPY_AND_ASSIGN(CapturingN
| |
145 scoped_ptr<TraceNetLogObserver> trace_net_log_observer_; | |
146 }; | |
147 | |
148 TEST_F(TraceNetLogObserverTest, TracingNotEnabled) { | |
149 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
150 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
151 | |
152 EndTraceAndFlush(); | |
153 trace_net_log_observer()->StopWatchForTraceStart(); | |
154 | |
155 size_t pos; | |
156 const base::DictionaryValue* item = FindTraceEntry( | |
157 NetLog::TYPE_REQUEST_ALIVE, pos); | |
158 EXPECT_FALSE(item); | |
159 } | |
160 | |
161 TEST_F(TraceNetLogObserverTest, TraceEventCaptured) { | |
mmenke
2014/08/27 19:03:15
Should have an event with PHASE_BEGIN and PHASE_EN
xunjieli
2014/09/02 16:37:33
Done. Thanks!
| |
162 CapturingNetLog::CapturedEntryList entries; | |
163 net_log()->GetEntries(&entries); | |
164 EXPECT_EQ(0u, entries.size()); | |
mmenke
2014/08/27 19:03:15
Just FYI, entries.empty() is generally preferred f
xunjieli
2014/09/02 16:37:33
Done. I see. Thanks!
| |
165 | |
166 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
167 EnableTraceLog(); | |
168 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
169 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
170 | |
171 net_log()->GetEntries(&entries); | |
172 ASSERT_EQ(2u, entries.size()); | |
173 | |
174 EndTraceAndFlush(); | |
175 trace_net_log_observer()->StopWatchForTraceStart(); | |
176 | |
177 size_t pos1; | |
178 size_t pos2; | |
179 const base::DictionaryValue* item1 = FindTraceEntry( | |
180 NetLog::TYPE_CANCELLED, pos1); | |
181 const base::DictionaryValue* item2 = FindTraceEntry( | |
182 NetLog::TYPE_REQUEST_ALIVE, pos2); | |
183 EXPECT_LT(pos1, pos2); | |
184 | |
185 std::string item1_phase, item2_phase; | |
mmenke
2014/08/27 19:03:15
These should be declared on separate lines.
xunjieli
2014/09/02 16:37:33
Done. Sorry, I missed this one. Thanks!
| |
186 EXPECT_TRUE(item1 && item1->GetString("ph", &item1_phase)); | |
187 EXPECT_TRUE(item2 && item2->GetString("ph", &item2_phase)); | |
mmenke
2014/08/27 19:03:15
Should just asserting on item1 / item2 when you tr
xunjieli
2014/09/02 16:37:33
Done.
| |
188 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NET_LOG_INSTANT), item1_phase); | |
189 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NET_LOG_INSTANT), item2_phase); | |
190 | |
191 std::string item1_id; | |
192 std::string item2_id; | |
193 EXPECT_TRUE(item1->GetString("id", &item1_id) && | |
194 item2->GetString("id", &item2_id)); | |
mmenke
2014/08/27 19:03:14
nit: Should have two separate EXPECTs, so if one
xunjieli
2014/09/02 16:37:34
Done.
| |
195 std::string item1_expected_id = | |
196 base::StringPrintf("0x%d", entries[0].source.id); | |
197 std::string item2_expected_id = | |
198 base::StringPrintf("0x%d", entries[1].source.id); | |
199 EXPECT_EQ(item1_expected_id, item1_id); | |
200 EXPECT_EQ(item2_expected_id, item2_id); | |
201 EXPECT_NE(item1_id, item2_id); | |
202 | |
203 std::string item1_source_type; | |
204 std::string item2_source_type; | |
205 EXPECT_TRUE(item1->GetString("args.source_type", &item1_source_type)); | |
206 EXPECT_TRUE(item2->GetString("args.source_type", &item2_source_type)); | |
207 | |
208 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), | |
209 item1_source_type); | |
210 EXPECT_EQ(NetLog::SourceTypeToString(entries[1].source.type), | |
211 item2_source_type); | |
212 | |
213 std::string item1_category; | |
214 std::string item2_category; | |
215 EXPECT_TRUE(item1->GetString("cat", &item1_category)); | |
216 EXPECT_TRUE(item2->GetString("cat", &item2_category)); | |
217 | |
218 EXPECT_EQ("netlog", item1_category); | |
219 EXPECT_EQ("netlog", item2_category); | |
mmenke
2014/08/27 19:03:14
Suggest making a utility function to clean up this
xunjieli
2014/09/02 16:37:34
Done. Thanks!
| |
220 | |
221 EXPECT_EQ(1u, FindTraceEntries(NetLog::TYPE_CANCELLED).size()); | |
222 EXPECT_EQ(1u, FindTraceEntries(NetLog::TYPE_REQUEST_ALIVE).size()); | |
223 } | |
224 | |
225 TEST_F(TraceNetLogObserverTest, EnableAndDisableTracing) { | |
226 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
227 EnableTraceLog(); | |
228 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
229 DisableTraceLog(); | |
230 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
231 EnableTraceLog(); | |
232 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
233 | |
234 EndTraceAndFlush(); | |
235 trace_net_log_observer()->StopWatchForTraceStart(); | |
236 | |
237 size_t pos1; | |
238 size_t pos2; | |
239 size_t pos3; | |
240 const base::DictionaryValue* item1 = FindTraceEntry( | |
241 NetLog::TYPE_CANCELLED, pos1); | |
242 const base::DictionaryValue* item2 = FindTraceEntry( | |
243 NetLog::TYPE_REQUEST_ALIVE, pos2); | |
244 const base::DictionaryValue* item3 = FindTraceEntry( | |
245 NetLog::TYPE_URL_REQUEST_START_JOB, pos3); | |
246 EXPECT_TRUE(item1); | |
247 EXPECT_FALSE(item2); | |
248 EXPECT_TRUE(item3); | |
249 EXPECT_LT(pos1, pos3); | |
250 | |
251 EXPECT_EQ(1u, FindTraceEntries(NetLog::TYPE_CANCELLED).size()); | |
252 EXPECT_EQ(1u, FindTraceEntries(NetLog::TYPE_URL_REQUEST_START_JOB).size()); | |
253 } | |
254 | |
255 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileTracing) { | |
256 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
257 EnableTraceLog(); | |
258 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
259 trace_net_log_observer()->StopWatchForTraceStart(); | |
260 ResetTraceNetLogObserver(NULL); | |
261 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
262 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
mmenke
2014/08/27 19:03:14
nit: Don't think we need the final entry.
xunjieli
2014/09/02 16:37:33
Done.
| |
263 | |
264 EndTraceAndFlush(); | |
265 | |
266 size_t pos1; | |
267 size_t pos2; | |
268 size_t pos3; | |
269 const base::DictionaryValue* item1 = FindTraceEntry( | |
270 NetLog::TYPE_CANCELLED, pos1); | |
271 const base::DictionaryValue* item2 = FindTraceEntry( | |
272 NetLog::TYPE_REQUEST_ALIVE, pos2); | |
273 const base::DictionaryValue* item3 = FindTraceEntry( | |
274 NetLog::TYPE_URL_REQUEST_START_JOB, pos3); | |
275 EXPECT_TRUE(item1); | |
276 EXPECT_FALSE(item2); | |
277 EXPECT_FALSE(item3); | |
278 | |
279 EXPECT_EQ(1u, FindTraceEntries(NetLog::TYPE_CANCELLED).size()); | |
280 } | |
281 | |
282 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileNotTracing) { | |
283 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
284 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
285 trace_net_log_observer()->StopWatchForTraceStart(); | |
286 ResetTraceNetLogObserver(NULL); | |
287 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
288 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
289 | |
290 EndTraceAndFlush(); | |
291 | |
292 size_t pos1; | |
293 size_t pos2; | |
294 size_t pos3; | |
295 const base::DictionaryValue* item1 = FindTraceEntry( | |
296 NetLog::TYPE_CANCELLED, pos1); | |
297 const base::DictionaryValue* item2 = FindTraceEntry( | |
298 NetLog::TYPE_REQUEST_ALIVE, pos2); | |
299 const base::DictionaryValue* item3 = FindTraceEntry( | |
300 NetLog::TYPE_URL_REQUEST_START_JOB, pos3); | |
301 EXPECT_FALSE(item1); | |
302 EXPECT_FALSE(item2); | |
303 EXPECT_FALSE(item3); | |
304 } | |
305 | |
306 TEST_F(TraceNetLogObserverTest, CreateObserverAfterTracingStarts) { | |
307 ResetTraceNetLogObserver(NULL); | |
308 EnableTraceLog(); | |
309 ResetTraceNetLogObserver(new TraceNetLogObserver()); | |
310 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
311 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
312 trace_net_log_observer()->StopWatchForTraceStart(); | |
313 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
314 net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
315 | |
316 EndTraceAndFlush(); | |
317 | |
318 size_t pos1; | |
319 size_t pos2; | |
320 size_t pos3; | |
321 const base::DictionaryValue* item1 = FindTraceEntry( | |
322 NetLog::TYPE_CANCELLED, pos1); | |
323 const base::DictionaryValue* item2 = FindTraceEntry( | |
324 NetLog::TYPE_REQUEST_ALIVE, pos2); | |
325 const base::DictionaryValue* item3 = FindTraceEntry( | |
326 NetLog::TYPE_URL_REQUEST_START_JOB, pos3); | |
327 EXPECT_FALSE(item1); | |
328 EXPECT_FALSE(item2); | |
329 EXPECT_FALSE(item3); | |
330 } | |
331 | |
332 TEST_F(TraceNetLogObserverTest, EventsWithAndWithoutParameters) { | |
333 trace_net_log_observer()->WatchForTraceStart(net_log()); | |
334 EnableTraceLog(); | |
335 NetLog::ParametersCallback net_log_callback; | |
336 std::string param = "bar"; | |
337 net_log_callback = NetLog::StringCallback("foo", | |
338 ¶m); | |
339 | |
340 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED, net_log_callback); | |
341 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
342 | |
343 EndTraceAndFlush(); | |
344 trace_net_log_observer()->StopWatchForTraceStart(); | |
345 | |
346 size_t pos1; | |
347 size_t pos2; | |
348 const base::DictionaryValue* item1 = FindTraceEntry( | |
349 NetLog::TYPE_CANCELLED, pos1); | |
350 const base::DictionaryValue* item2 = FindTraceEntry( | |
351 NetLog::TYPE_REQUEST_ALIVE, pos2); | |
352 EXPECT_LT(pos1, pos2); | |
353 | |
354 std::string item1_params; | |
355 std::string item2_params; | |
356 EXPECT_TRUE(item1 && item1->GetString("args.params.foo", &item1_params)); | |
357 EXPECT_EQ("bar", item1_params); | |
358 | |
359 EXPECT_TRUE(item2 && item2->GetString("args.params", &item2_params)); | |
360 EXPECT_TRUE(item2_params.empty()); | |
361 | |
362 EXPECT_EQ(1u, FindTraceEntries(NetLog::TYPE_CANCELLED).size()); | |
363 EXPECT_EQ(1u, FindTraceEntries(NetLog::TYPE_REQUEST_ALIVE).size()); | |
364 } | |
365 | |
366 } // namespace | |
367 | |
368 } // namespace net | |
OLD | NEW |