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 "base/debug/trace_event.h" | |
8 | |
mmenke
2014/08/21 15:35:40
nit: Remove blank line.
xunjieli
2014/08/22 17:20:10
Done.
| |
9 #include "base/json/json_reader.h" | |
10 #include "base/values.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
mmenke
2014/08/21 15:35:41
Should include NetLog and TraceLog headers (They'r
xunjieli
2014/08/22 17:20:11
Done.
| |
12 | |
13 namespace net { | |
14 | |
15 namespace { | |
16 | |
17 using namespace base; | |
xunjieli
2014/08/20 22:00:43
I think this "using namespace" directive is not re
mmenke
2014/08/21 15:35:40
It's not too common in net/, but you can use indiv
xunjieli
2014/08/22 17:20:11
Done. Thanks!
| |
18 | |
19 // A net log that logs all events by default. | |
20 class MyTestNetLog : public net::NetLog { | |
21 public: | |
22 MyTestNetLog() { | |
23 SetBaseLogLevel(LOG_ALL); | |
mmenke
2014/08/21 15:35:40
This class shouldn't be needed - the NetLog should
xunjieli
2014/08/22 17:20:11
Done. Thanks!
| |
24 } | |
25 virtual ~MyTestNetLog() {} | |
26 }; | |
27 | |
28 class TraceNetLogObserverTest : public testing::Test { | |
29 public: | |
30 void OnTraceDataCollected( | |
31 const scoped_refptr<RefCountedString>& events_str, | |
mmenke
2014/08/21 15:35:40
Should include base/memory/ref_counted.h, and ref_
xunjieli
2014/08/22 17:20:11
Done.
| |
32 bool has_more_events); | |
mmenke
2014/08/21 15:35:41
nit: Should inline all functions, to be consisten
xunjieli
2014/08/22 17:20:10
Done.
| |
33 void Clear() { | |
mmenke
2014/08/21 15:35:41
nit: Blank line before clear.
xunjieli
2014/08/22 17:20:10
Done.
| |
34 trace_parsed_.Clear(); | |
35 json_output_.json_output.clear(); | |
36 } | |
37 | |
38 void EnableTraceLog() { | |
39 debug::TraceLog::GetInstance()->SetEnabled( | |
40 debug::CategoryFilter("*"), | |
41 debug::TraceLog::RECORDING_MODE, | |
42 debug::TraceOptions()); | |
43 } | |
44 | |
45 void DisableTraceLog() { | |
46 debug::TraceLog::GetInstance()->SetDisabled(); | |
47 } | |
48 | |
49 void EndTraceAndFlush() { | |
50 debug::TraceLog::GetInstance()->SetDisabled(); | |
51 debug::TraceLog::GetInstance()->Flush( | |
52 Bind(&TraceNetLogObserverTest::OnTraceDataCollected, | |
53 Unretained(this))); | |
54 } | |
55 | |
56 virtual void SetUp() OVERRIDE { | |
mmenke
2014/08/21 15:35:40
nit: Suggest putting SetUp and TearDown first.
xunjieli
2014/08/22 17:20:10
Done. Thanks!
| |
57 debug::TraceLog::DeleteForTesting(); | |
58 debug::TraceLog* tracelog = debug::TraceLog::GetInstance(); | |
59 ASSERT_TRUE(tracelog); | |
60 ASSERT_FALSE(tracelog->IsEnabled()); | |
61 trace_buffer_.SetOutputCallback(json_output_.GetCallback()); | |
62 net_log_.reset(new MyTestNetLog); | |
63 trace_net_log_observer_.reset(new TraceNetLogObserver()); | |
64 // TODO(xunjieli): not sure whether this is okay. | |
65 debug::TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop(); | |
66 } | |
67 | |
68 virtual void TearDown() OVERRIDE { | |
69 if (debug::TraceLog::GetInstance()) | |
mmenke
2014/08/21 15:35:41
Is this conditional needed? Looks like it always
xunjieli
2014/08/22 17:20:11
Done. Right, I think it is not needed. Thanks!
| |
70 EXPECT_FALSE(debug::TraceLog::GetInstance()->IsEnabled()); | |
71 debug::TraceLog::DeleteForTesting(); | |
72 } | |
73 | |
74 ListValue trace_parsed_; | |
mmenke
2014/08/21 15:35:41
These should be private, with accessors as needed.
xunjieli
2014/08/22 17:20:11
Done. Got it. Thanks!
| |
75 debug::TraceResultBuffer trace_buffer_; | |
76 debug::TraceResultBuffer::SimpleOutput json_output_; | |
77 scoped_ptr<NetLog> net_log_; | |
78 scoped_ptr<TraceNetLogObserver> trace_net_log_observer_; | |
mmenke
2014/08/21 15:35:40
Should include the scoped_ptr header.
xunjieli
2014/08/22 17:20:10
Done.
| |
79 }; | |
80 | |
81 | |
82 void TraceNetLogObserverTest::OnTraceDataCollected( | |
83 const scoped_refptr<RefCountedString>& events_str, | |
84 bool has_more_events) { | |
85 json_output_.json_output.clear(); | |
mmenke
2014/08/21 15:35:40
DCHECK(trace_parsed_.empty());?
(DCHECK instead o
xunjieli
2014/08/22 17:20:11
Done. Thanks!
| |
86 trace_buffer_.Start(); | |
87 trace_buffer_.AddFragment(events_str->data()); | |
88 trace_buffer_.Finish(); | |
89 | |
90 scoped_ptr<Value> root; | |
mmenke
2014/08/21 15:35:41
trace_value, maybe?
xunjieli
2014/08/22 17:20:11
Done.
| |
91 root.reset(JSONReader::Read(json_output_.json_output, | |
92 JSON_PARSE_RFC | JSON_DETACHABLE_CHILDREN)); | |
93 | |
94 if (!root.get()) { | |
95 LOG(ERROR) << json_output_.json_output; | |
96 } | |
mmenke
2014/08/21 15:35:41
This can be replaced with:
ASSERT_TRUE(root) << j
xunjieli
2014/08/22 17:20:11
Done. Thanks! That's convenient!
| |
97 | |
98 ListValue* root_list = NULL; | |
99 ASSERT_TRUE(root.get()); | |
100 ASSERT_TRUE(root->GetAsList(&root_list)); | |
101 | |
102 while (root_list->GetSize()) { | |
mmenke
2014/08/21 15:35:41
Rather than copying, this can be replaced with:
t
mmenke
2014/08/21 15:35:42
suggest renaming root_list to trace_events and tra
xunjieli
2014/08/22 17:20:11
Done. Thanks!
| |
103 scoped_ptr<Value> item; | |
104 root_list->Remove(0, &item); | |
105 trace_parsed_.Append(item.release()); | |
106 } | |
107 } | |
108 | |
109 bool IsStringInDict(const char* string_to_match, const DictionaryValue* dict) { | |
110 for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { | |
111 if (it.key().find(string_to_match) != std::string::npos) | |
112 return true; | |
113 | |
114 std::string value_str; | |
mmenke
2014/08/21 15:35:40
Should include <string>
xunjieli
2014/08/22 17:20:10
Done.
| |
115 it.value().GetAsString(&value_str); | |
116 if (value_str.find(string_to_match) != std::string::npos) | |
117 return true; | |
118 } | |
119 | |
120 // Recurse to test arguments | |
121 const DictionaryValue* args_dict = NULL; | |
122 dict->GetDictionary("args", &args_dict); | |
123 if (args_dict) | |
124 return IsStringInDict(string_to_match, args_dict); | |
mmenke
2014/08/21 15:35:41
This seems much too broad. Surely we know just wh
xunjieli
2014/08/22 17:20:10
Done. You are right! Thanks!
| |
125 | |
126 return false; | |
127 } | |
128 | |
129 const DictionaryValue* FindTraceEntry( | |
130 const ListValue& trace_parsed, | |
mmenke
2014/08/21 15:35:41
Since this is a member of the class, don't need to
xunjieli
2014/08/22 17:20:11
Done.
| |
131 const char* string_to_match) { | |
mmenke
2014/08/21 15:35:41
Maybe call this event_type, and just take raw NetL
xunjieli
2014/08/22 17:20:10
Done. That's smart. Thank you!
| |
132 // Scan all items | |
133 size_t trace_parsed_count = trace_parsed.GetSize(); | |
134 for (size_t i = 0; i < trace_parsed_count; i++) { | |
135 const Value* value = NULL; | |
136 trace_parsed.Get(i, &value); | |
137 if (!value || value->GetType() != Value::TYPE_DICTIONARY) | |
138 continue; | |
139 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value); | |
mmenke
2014/08/21 15:35:41
Should get rid of the type check, and use value->G
xunjieli
2014/08/22 17:20:10
Done.
| |
140 | |
141 if (IsStringInDict(string_to_match, dict)) | |
mmenke
2014/08/21 15:35:41
Again, it seems like we should know exactly where
xunjieli
2014/08/22 17:20:11
Done.
| |
142 return dict; | |
143 } | |
144 return NULL; | |
145 } | |
146 | |
147 } // namespace | |
mmenke
2014/08/21 15:35:42
Can just extend the anonymous namespace to the end
xunjieli
2014/08/22 17:20:10
Done.
| |
148 | |
149 TEST_F(TraceNetLogObserverTest, TracingNotEnabled) { | |
150 trace_net_log_observer_->WatchForTraceStart(net_log_.get()); | |
151 net_log_->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
152 | |
153 EndTraceAndFlush(); | |
154 | |
155 trace_net_log_observer_->StopWatchForTraceStart(); | |
156 const DictionaryValue* item = FindTraceEntry( | |
157 trace_parsed_, | |
158 NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE)); | |
159 EXPECT_FALSE(item); | |
160 } | |
161 | |
162 | |
163 TEST_F(TraceNetLogObserverTest, TraceEventCaptured) { | |
164 trace_net_log_observer_->WatchForTraceStart(net_log_.get()); | |
165 EnableTraceLog(); | |
166 net_log_->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
167 | |
168 EndTraceAndFlush(); | |
169 | |
170 const DictionaryValue* item = FindTraceEntry( | |
171 trace_parsed_, | |
172 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED)); | |
173 EXPECT_TRUE(item); | |
mmenke
2014/08/21 15:35:40
Also, maybe log a second event, and make sure orde
mmenke
2014/08/21 15:35:40
Also, should check other values as well - make sur
mmenke
2014/08/21 15:35:41
Should we make sure there's only one such event?
xunjieli
2014/08/22 17:20:10
Done.
xunjieli
2014/08/22 17:20:11
Done.
xunjieli
2014/08/22 17:20:11
Done.
| |
174 } | |
175 | |
176 TEST_F(TraceNetLogObserverTest, EnableAndDisableTracing) { | |
177 trace_net_log_observer_->WatchForTraceStart(net_log_.get()); | |
178 EnableTraceLog(); | |
179 net_log_->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
180 DisableTraceLog(); | |
181 net_log_->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
182 EnableTraceLog(); | |
183 net_log_->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
184 | |
185 EndTraceAndFlush(); | |
186 | |
187 const DictionaryValue* item1 = FindTraceEntry( | |
188 trace_parsed_, | |
189 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED)); | |
190 const DictionaryValue* item2 = FindTraceEntry( | |
191 trace_parsed_, | |
192 NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE)); | |
193 const DictionaryValue* item3 = FindTraceEntry( | |
194 trace_parsed_, | |
195 NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB)); | |
196 EXPECT_TRUE(item1); | |
197 EXPECT_FALSE(item2); | |
198 EXPECT_TRUE(item3); | |
199 } | |
200 | |
201 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileTracing) { | |
202 trace_net_log_observer_->WatchForTraceStart(net_log_.get()); | |
203 EnableTraceLog(); | |
204 net_log_->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
205 trace_net_log_observer_->StopWatchForTraceStart(); | |
206 trace_net_log_observer_.reset(NULL); | |
xunjieli
2014/08/20 22:00:43
Matt, if I just reset the observer scope_ptr, the
mmenke
2014/08/21 15:35:41
Yes, this is just what you should be doing.
xunjieli
2014/08/22 17:20:11
Done. Thanks!
| |
207 net_log_->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
208 net_log_->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
209 | |
210 EndTraceAndFlush(); | |
211 | |
212 const DictionaryValue* item1 = FindTraceEntry( | |
213 trace_parsed_, | |
214 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED)); | |
215 const DictionaryValue* item2 = FindTraceEntry( | |
216 trace_parsed_, | |
217 NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE)); | |
218 const DictionaryValue* item3 = FindTraceEntry( | |
219 trace_parsed_, | |
220 NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB)); | |
221 EXPECT_TRUE(item1); | |
222 EXPECT_FALSE(item2); | |
223 EXPECT_FALSE(item3); | |
224 } | |
225 | |
226 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileNotTracing) { | |
227 trace_net_log_observer_->WatchForTraceStart(net_log_.get()); | |
228 net_log_->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
229 trace_net_log_observer_->StopWatchForTraceStart(); | |
230 trace_net_log_observer_.reset(NULL); | |
231 net_log_->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
232 net_log_->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
233 | |
234 EndTraceAndFlush(); | |
235 | |
236 const DictionaryValue* item1 = FindTraceEntry( | |
237 trace_parsed_, | |
238 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED)); | |
239 const DictionaryValue* item2 = FindTraceEntry( | |
240 trace_parsed_, | |
241 NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE)); | |
242 const DictionaryValue* item3 = FindTraceEntry( | |
243 trace_parsed_, | |
244 NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB)); | |
245 EXPECT_FALSE(item1); | |
246 EXPECT_FALSE(item2); | |
247 EXPECT_FALSE(item3); | |
248 } | |
249 /** | |
250 TEST_F(TraceNetLogObserverTest, CreateObserverAfterTracingStarts) { | |
251 trace_net_log_observer_.reset(NULL); | |
252 EnableTraceLog(); | |
253 trace_net_log_observer_.reset(new TraceNetLogObserver()); | |
xunjieli
2014/08/20 22:00:43
If we start the observer after Tracing is enabled,
mmenke
2014/08/21 15:35:41
This is probably expected behavior. I suggest jus
xunjieli
2014/08/22 17:20:10
I see. Thanks!
On 2014/08/21 15:35:41, mmenke wrot
| |
254 trace_net_log_observer_->WatchForTraceStart(net_log_.get()); | |
255 net_log_->AddGlobalEntry(NetLog::TYPE_CANCELLED); | |
256 trace_net_log_observer_->StopWatchForTraceStart(); | |
257 net_log_->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
258 net_log_->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); | |
259 | |
260 EndTraceAndFlush(); | |
261 | |
262 const DictionaryValue* item1 = FindTraceEntry( | |
263 trace_parsed_, | |
264 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED)); | |
265 const DictionaryValue* item2 = FindTraceEntry( | |
266 trace_parsed_, | |
267 NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE)); | |
268 const DictionaryValue* item3 = FindTraceEntry( | |
269 trace_parsed_, | |
270 NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB)); | |
271 EXPECT_TRUE(item1); | |
272 EXPECT_FALSE(item2); | |
273 EXPECT_FALSE(item3); | |
274 } **/ | |
275 | |
276 TEST_F(TraceNetLogObserverTest, EventsWithAndWithoutParameters) { | |
277 trace_net_log_observer_->WatchForTraceStart(net_log_.get()); | |
278 EnableTraceLog(); | |
279 NetLog::ParametersCallback net_log_callback; | |
280 std::string param = "bar"; | |
281 net_log_callback = NetLog::StringCallback("foo", | |
282 ¶m); | |
283 | |
284 net_log_->AddGlobalEntry(NetLog::TYPE_CANCELLED, net_log_callback); | |
285 net_log_->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | |
286 | |
287 EndTraceAndFlush(); | |
288 | |
289 const DictionaryValue* item1 = FindTraceEntry( | |
290 trace_parsed_, | |
291 NetLog::EventTypeToString(NetLog::TYPE_CANCELLED)); | |
292 EXPECT_TRUE(item1); | |
293 const DictionaryValue* item1_args = NULL; | |
294 item1->GetDictionary("args", &item1_args); | |
295 EXPECT_TRUE(item1_args); | |
296 const DictionaryValue* item1_value = NULL; | |
297 item1_args->GetDictionary("value", &item1_value); | |
298 EXPECT_TRUE(item1_value); | |
299 const DictionaryValue* item1_params = NULL; | |
300 item1_value->GetDictionary("params", &item1_params); | |
301 EXPECT_TRUE(item1_params); | |
302 std::string actual_value; | |
303 item1_params->GetString("foo", &actual_value); | |
304 EXPECT_EQ("bar", actual_value); | |
mmenke
2014/08/21 15:35:41
Dictionaries support recursion, I believe, so this
xunjieli
2014/08/22 17:20:11
Done. Thanks for letting me know!
| |
305 | |
306 const DictionaryValue* item2 = FindTraceEntry( | |
307 trace_parsed_, | |
308 NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE)); | |
309 EXPECT_TRUE(item2); | |
310 const DictionaryValue* item2_args = NULL; | |
311 item2->GetDictionary("args", &item2_args); | |
312 EXPECT_TRUE(item2_args); | |
313 const DictionaryValue* item2_value = NULL; | |
314 item2_args->GetDictionary("value", &item2_value); | |
315 EXPECT_TRUE(item2_value); | |
316 const DictionaryValue* item2_params = NULL; | |
317 item2_value->GetDictionary("params", &item2_params); | |
318 EXPECT_FALSE(item2_params); | |
319 } | |
mmenke
2014/08/21 15:35:40
nit: Blank line before ending a namespace.
xunjieli
2014/08/22 17:20:12
Done.
| |
320 } // namespace net | |
OLD | NEW |