| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/trace_net_log_observer.h" | 5 #include "net/base/trace_net_log_observer.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/debug/trace_event_impl.h" | 11 #include "base/debug/trace_event_impl.h" |
| 12 #include "base/json/json_reader.h" | 12 #include "base/json/json_reader.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 15 #include "base/memory/ref_counted_memory.h" | 15 #include "base/memory/ref_counted_memory.h" |
| 16 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 17 #include "base/run_loop.h" | 17 #include "base/run_loop.h" |
| 18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
| 19 #include "base/values.h" | 19 #include "base/values.h" |
| 20 #include "net/base/capturing_net_log.h" | 20 #include "net/base/capturing_net_log.h" |
| 21 #include "net/base/net_log.h" | 21 #include "net/base/net_log.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 23 |
| 24 using base::debug::TraceLog; | 24 using base::debug::TraceLog; |
| 25 | 25 |
| 26 namespace net { | 26 namespace net { |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 // TraceLog category for NetLog events. |
| 31 const char kNetLogTracingCategory[] = TRACE_DISABLED_BY_DEFAULT("netlog"); |
| 32 |
| 30 struct TraceEntryInfo { | 33 struct TraceEntryInfo { |
| 31 std::string category; | 34 std::string category; |
| 32 std::string id; | 35 std::string id; |
| 33 std::string phase; | 36 std::string phase; |
| 34 std::string name; | 37 std::string name; |
| 35 std::string source_type; | 38 std::string source_type; |
| 36 }; | 39 }; |
| 37 | 40 |
| 38 TraceEntryInfo GetTraceEntryInfoFromValue(const base::DictionaryValue& value) { | 41 TraceEntryInfo GetTraceEntryInfoFromValue(const base::DictionaryValue& value) { |
| 39 TraceEntryInfo info; | 42 TraceEntryInfo info; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 base::ListValue* trace_events = NULL; | 82 base::ListValue* trace_events = NULL; |
| 80 ASSERT_TRUE(trace_value->GetAsList(&trace_events)); | 83 ASSERT_TRUE(trace_value->GetAsList(&trace_events)); |
| 81 | 84 |
| 82 trace_events_ = FilterNetLogTraceEvents(*trace_events); | 85 trace_events_ = FilterNetLogTraceEvents(*trace_events); |
| 83 | 86 |
| 84 if (!has_more_events) | 87 if (!has_more_events) |
| 85 run_loop->Quit(); | 88 run_loop->Quit(); |
| 86 } | 89 } |
| 87 | 90 |
| 88 static void EnableTraceLog() { | 91 static void EnableTraceLog() { |
| 89 TraceLog::GetInstance()->SetEnabled(base::debug::CategoryFilter("netlog"), | 92 TraceLog::GetInstance()->SetEnabled( |
| 90 TraceLog::RECORDING_MODE, | 93 base::debug::CategoryFilter(kNetLogTracingCategory), |
| 91 base::debug::TraceOptions()); | 94 TraceLog::RECORDING_MODE, |
| 95 base::debug::TraceOptions()); |
| 92 } | 96 } |
| 93 | 97 |
| 94 void EndTraceAndFlush() { | 98 void EndTraceAndFlush() { |
| 95 base::RunLoop run_loop; | 99 base::RunLoop run_loop; |
| 96 TraceLog::GetInstance()->SetDisabled(); | 100 TraceLog::GetInstance()->SetDisabled(); |
| 97 TraceLog::GetInstance()->Flush( | 101 TraceLog::GetInstance()->Flush( |
| 98 base::Bind(&TraceNetLogObserverTest::OnTraceDataCollected, | 102 base::Bind(&TraceNetLogObserverTest::OnTraceDataCollected, |
| 99 base::Unretained(this), | 103 base::Unretained(this), |
| 100 base::Unretained(&run_loop))); | 104 base::Unretained(&run_loop))); |
| 101 run_loop.Run(); | 105 run_loop.Run(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 113 if (!trace_events.GetDictionary(i, &dict)) { | 117 if (!trace_events.GetDictionary(i, &dict)) { |
| 114 ADD_FAILURE() << "Unexpected non-dictionary event in trace_events"; | 118 ADD_FAILURE() << "Unexpected non-dictionary event in trace_events"; |
| 115 continue; | 119 continue; |
| 116 } | 120 } |
| 117 std::string category; | 121 std::string category; |
| 118 if (!dict->GetString("cat", &category)) { | 122 if (!dict->GetString("cat", &category)) { |
| 119 ADD_FAILURE() | 123 ADD_FAILURE() |
| 120 << "Unexpected item without a category field in trace_events"; | 124 << "Unexpected item without a category field in trace_events"; |
| 121 continue; | 125 continue; |
| 122 } | 126 } |
| 123 if (category != "netlog") | 127 if (category != kNetLogTracingCategory) |
| 124 continue; | 128 continue; |
| 125 filtered_trace_events->Append(dict->DeepCopy()); | 129 filtered_trace_events->Append(dict->DeepCopy()); |
| 126 } | 130 } |
| 127 return filtered_trace_events.Pass(); | 131 return filtered_trace_events.Pass(); |
| 128 } | 132 } |
| 129 | 133 |
| 130 base::ListValue* trace_events() const { | 134 base::ListValue* trace_events() const { |
| 131 return trace_events_.get(); | 135 return trace_events_.get(); |
| 132 } | 136 } |
| 133 | 137 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 const base::DictionaryValue* item1 = NULL; | 182 const base::DictionaryValue* item1 = NULL; |
| 179 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); | 183 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); |
| 180 const base::DictionaryValue* item2 = NULL; | 184 const base::DictionaryValue* item2 = NULL; |
| 181 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); | 185 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); |
| 182 const base::DictionaryValue* item3 = NULL; | 186 const base::DictionaryValue* item3 = NULL; |
| 183 ASSERT_TRUE(trace_events()->GetDictionary(2, &item3)); | 187 ASSERT_TRUE(trace_events()->GetDictionary(2, &item3)); |
| 184 | 188 |
| 185 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); | 189 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); |
| 186 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); | 190 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); |
| 187 TraceEntryInfo actual_item3 = GetTraceEntryInfoFromValue(*item3); | 191 TraceEntryInfo actual_item3 = GetTraceEntryInfoFromValue(*item3); |
| 188 EXPECT_EQ("netlog", actual_item1.category); | 192 EXPECT_EQ(kNetLogTracingCategory, actual_item1.category); |
| 189 EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); | 193 EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); |
| 190 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | 194 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), |
| 191 actual_item1.phase); | 195 actual_item1.phase); |
| 192 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), | 196 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), |
| 193 actual_item1.name); | 197 actual_item1.name); |
| 194 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), | 198 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), |
| 195 actual_item1.source_type); | 199 actual_item1.source_type); |
| 196 | 200 |
| 197 EXPECT_EQ("netlog", actual_item2.category); | 201 EXPECT_EQ(kNetLogTracingCategory, actual_item2.category); |
| 198 EXPECT_EQ(base::StringPrintf("0x%d", entries[1].source.id), actual_item2.id); | 202 EXPECT_EQ(base::StringPrintf("0x%d", entries[1].source.id), actual_item2.id); |
| 199 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN), | 203 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN), |
| 200 actual_item2.phase); | 204 actual_item2.phase); |
| 201 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB), | 205 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB), |
| 202 actual_item2.name); | 206 actual_item2.name); |
| 203 EXPECT_EQ(NetLog::SourceTypeToString(entries[1].source.type), | 207 EXPECT_EQ(NetLog::SourceTypeToString(entries[1].source.type), |
| 204 actual_item2.source_type); | 208 actual_item2.source_type); |
| 205 | 209 |
| 206 EXPECT_EQ("netlog", actual_item3.category); | 210 EXPECT_EQ(kNetLogTracingCategory, actual_item3.category); |
| 207 EXPECT_EQ(base::StringPrintf("0x%d", entries[2].source.id), actual_item3.id); | 211 EXPECT_EQ(base::StringPrintf("0x%d", entries[2].source.id), actual_item3.id); |
| 208 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END), | 212 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END), |
| 209 actual_item3.phase); | 213 actual_item3.phase); |
| 210 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE), | 214 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE), |
| 211 actual_item3.name); | 215 actual_item3.name); |
| 212 EXPECT_EQ(NetLog::SourceTypeToString(entries[2].source.type), | 216 EXPECT_EQ(NetLog::SourceTypeToString(entries[2].source.type), |
| 213 actual_item3.source_type); | 217 actual_item3.source_type); |
| 214 } | 218 } |
| 215 | 219 |
| 216 TEST_F(TraceNetLogObserverTest, EnableAndDisableTracing) { | 220 TEST_F(TraceNetLogObserverTest, EnableAndDisableTracing) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 229 net_log()->GetEntries(&entries); | 233 net_log()->GetEntries(&entries); |
| 230 EXPECT_EQ(3u, entries.size()); | 234 EXPECT_EQ(3u, entries.size()); |
| 231 EXPECT_EQ(2u, trace_events()->GetSize()); | 235 EXPECT_EQ(2u, trace_events()->GetSize()); |
| 232 const base::DictionaryValue* item1 = NULL; | 236 const base::DictionaryValue* item1 = NULL; |
| 233 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); | 237 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); |
| 234 const base::DictionaryValue* item2 = NULL; | 238 const base::DictionaryValue* item2 = NULL; |
| 235 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); | 239 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); |
| 236 | 240 |
| 237 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); | 241 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); |
| 238 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); | 242 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); |
| 239 EXPECT_EQ("netlog", actual_item1.category); | 243 EXPECT_EQ(kNetLogTracingCategory, actual_item1.category); |
| 240 EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); | 244 EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); |
| 241 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | 245 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), |
| 242 actual_item1.phase); | 246 actual_item1.phase); |
| 243 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), | 247 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), |
| 244 actual_item1.name); | 248 actual_item1.name); |
| 245 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), | 249 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), |
| 246 actual_item1.source_type); | 250 actual_item1.source_type); |
| 247 | 251 |
| 248 EXPECT_EQ("netlog", actual_item2.category); | 252 EXPECT_EQ(kNetLogTracingCategory, actual_item2.category); |
| 249 EXPECT_EQ(base::StringPrintf("0x%d", entries[2].source.id), actual_item2.id); | 253 EXPECT_EQ(base::StringPrintf("0x%d", entries[2].source.id), actual_item2.id); |
| 250 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | 254 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), |
| 251 actual_item2.phase); | 255 actual_item2.phase); |
| 252 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB), | 256 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB), |
| 253 actual_item2.name); | 257 actual_item2.name); |
| 254 EXPECT_EQ(NetLog::SourceTypeToString(entries[2].source.type), | 258 EXPECT_EQ(NetLog::SourceTypeToString(entries[2].source.type), |
| 255 actual_item2.source_type); | 259 actual_item2.source_type); |
| 256 } | 260 } |
| 257 | 261 |
| 258 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileTracing) { | 262 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileTracing) { |
| 259 trace_net_log_observer()->WatchForTraceStart(net_log()); | 263 trace_net_log_observer()->WatchForTraceStart(net_log()); |
| 260 EnableTraceLog(); | 264 EnableTraceLog(); |
| 261 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); | 265 net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); |
| 262 trace_net_log_observer()->StopWatchForTraceStart(); | 266 trace_net_log_observer()->StopWatchForTraceStart(); |
| 263 set_trace_net_log_observer(NULL); | 267 set_trace_net_log_observer(NULL); |
| 264 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); | 268 net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); |
| 265 | 269 |
| 266 EndTraceAndFlush(); | 270 EndTraceAndFlush(); |
| 267 | 271 |
| 268 CapturingNetLog::CapturedEntryList entries; | 272 CapturingNetLog::CapturedEntryList entries; |
| 269 net_log()->GetEntries(&entries); | 273 net_log()->GetEntries(&entries); |
| 270 EXPECT_EQ(2u, entries.size()); | 274 EXPECT_EQ(2u, entries.size()); |
| 271 EXPECT_EQ(1u, trace_events()->GetSize()); | 275 EXPECT_EQ(1u, trace_events()->GetSize()); |
| 272 | 276 |
| 273 const base::DictionaryValue* item1 = NULL; | 277 const base::DictionaryValue* item1 = NULL; |
| 274 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); | 278 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); |
| 275 | 279 |
| 276 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); | 280 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); |
| 277 EXPECT_EQ("netlog", actual_item1.category); | 281 EXPECT_EQ(kNetLogTracingCategory, actual_item1.category); |
| 278 EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); | 282 EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); |
| 279 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | 283 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), |
| 280 actual_item1.phase); | 284 actual_item1.phase); |
| 281 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), | 285 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), |
| 282 actual_item1.name); | 286 actual_item1.name); |
| 283 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), | 287 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), |
| 284 actual_item1.source_type); | 288 actual_item1.source_type); |
| 285 } | 289 } |
| 286 | 290 |
| 287 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileNotTracing) { | 291 TEST_F(TraceNetLogObserverTest, DestroyObserverWhileNotTracing) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 net_log()->GetEntries(&entries); | 339 net_log()->GetEntries(&entries); |
| 336 EXPECT_EQ(2u, entries.size()); | 340 EXPECT_EQ(2u, entries.size()); |
| 337 EXPECT_EQ(2u, trace_events()->GetSize()); | 341 EXPECT_EQ(2u, trace_events()->GetSize()); |
| 338 const base::DictionaryValue* item1 = NULL; | 342 const base::DictionaryValue* item1 = NULL; |
| 339 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); | 343 ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); |
| 340 const base::DictionaryValue* item2 = NULL; | 344 const base::DictionaryValue* item2 = NULL; |
| 341 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); | 345 ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); |
| 342 | 346 |
| 343 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); | 347 TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); |
| 344 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); | 348 TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); |
| 345 EXPECT_EQ("netlog", actual_item1.category); | 349 EXPECT_EQ(kNetLogTracingCategory, actual_item1.category); |
| 346 EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); | 350 EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); |
| 347 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | 351 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), |
| 348 actual_item1.phase); | 352 actual_item1.phase); |
| 349 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), | 353 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), |
| 350 actual_item1.name); | 354 actual_item1.name); |
| 351 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), | 355 EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), |
| 352 actual_item1.source_type); | 356 actual_item1.source_type); |
| 353 | 357 |
| 354 EXPECT_EQ("netlog", actual_item2.category); | 358 EXPECT_EQ(kNetLogTracingCategory, actual_item2.category); |
| 355 EXPECT_EQ(base::StringPrintf("0x%d", entries[1].source.id), actual_item2.id); | 359 EXPECT_EQ(base::StringPrintf("0x%d", entries[1].source.id), actual_item2.id); |
| 356 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), | 360 EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), |
| 357 actual_item2.phase); | 361 actual_item2.phase); |
| 358 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE), | 362 EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE), |
| 359 actual_item2.name); | 363 actual_item2.name); |
| 360 EXPECT_EQ(NetLog::SourceTypeToString(entries[1].source.type), | 364 EXPECT_EQ(NetLog::SourceTypeToString(entries[1].source.type), |
| 361 actual_item2.source_type); | 365 actual_item2.source_type); |
| 362 | 366 |
| 363 std::string item1_params; | 367 std::string item1_params; |
| 364 std::string item2_params; | 368 std::string item2_params; |
| 365 EXPECT_TRUE(item1->GetString("args.params.foo", &item1_params)); | 369 EXPECT_TRUE(item1->GetString("args.params.foo", &item1_params)); |
| 366 EXPECT_EQ("bar", item1_params); | 370 EXPECT_EQ("bar", item1_params); |
| 367 | 371 |
| 368 EXPECT_TRUE(item2->GetString("args.params", &item2_params)); | 372 EXPECT_TRUE(item2->GetString("args.params", &item2_params)); |
| 369 EXPECT_TRUE(item2_params.empty()); | 373 EXPECT_TRUE(item2_params.empty()); |
| 370 } | 374 } |
| 371 | 375 |
| 372 } // namespace | 376 } // namespace |
| 373 | 377 |
| 374 } // namespace net | 378 } // namespace net |
| OLD | NEW |