1 // Copyright 2015 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 <stddef.h>
6
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/macros.h"
10 #include "base/trace_event/memory_dump_manager.h"
11 #include "base/trace_event/trace_config.h"
12 #include "base/trace_event/trace_config_memory_test_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace base {
16 namespace trace_event {
17
18 namespace {
19
20 const char kDefaultTraceConfigString[] =
21 "{"
22 "\"enable_argument_filter\":false,"
23 "\"enable_systrace\":false,"
24 "\"record_mode\":\"record-until-full\""
25 "}";
26
27 const char kCustomTraceConfigString[] =
28 "{"
29 "\"enable_argument_filter\":true,"
30 "\"enable_systrace\":true,"
31 "\"event_filters\":["
32 "{"
33 "\"excluded_categories\":[\"unfiltered_cat\"],"
34 "\"filter_args\":{\"event_name_whitelist\":[\"a snake\",\"a dog\"]},"
35 "\"filter_predicate\":\"event_whitelist_predicate\","
36 "\"included_categories\":[\"*\"]"
37 "}"
38 "],"
39 "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
40 "\"included_categories\":["
41 "\"included\","
42 "\"inc_pattern*\","
43 "\"disabled-by-default-cc\","
44 "\"disabled-by-default-memory-infra\"],"
45 "\"memory_dump_config\":{"
46 "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"],"
47 "\"heap_profiler_options\":{"
48 "\"breakdown_threshold_bytes\":10240"
49 "},"
50 "\"triggers\":["
51 "{"
52 "\"min_time_between_dumps_ms\":50,"
53 "\"mode\":\"light\","
54 "\"type\":\"periodic_interval\""
55 "},"
56 "{"
57 "\"min_time_between_dumps_ms\":1000,"
58 "\"mode\":\"detailed\","
59 "\"type\":\"periodic_interval\""
60 "}"
61 "]"
62 "},"
63 "\"record_mode\":\"record-continuously\""
64 "}";
65
CheckDefaultTraceConfigBehavior(const TraceConfig & tc)66 void CheckDefaultTraceConfigBehavior(const TraceConfig& tc) {
67 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
68 EXPECT_FALSE(tc.IsSystraceEnabled());
69 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
70
71 // Default trace config enables every category filter except the
72 // disabled-by-default-* ones.
73 EXPECT_TRUE(tc.IsCategoryGroupEnabled("Category1"));
74 EXPECT_TRUE(tc.IsCategoryGroupEnabled("not-excluded-category"));
75 EXPECT_FALSE(tc.IsCategoryGroupEnabled("disabled-by-default-cc"));
76
77 EXPECT_TRUE(tc.IsCategoryGroupEnabled("Category1,not-excluded-category"));
78 EXPECT_TRUE(tc.IsCategoryGroupEnabled("Category1,disabled-by-default-cc"));
79 EXPECT_FALSE(tc.IsCategoryGroupEnabled(
80 "disabled-by-default-cc,disabled-by-default-cc2"));
81 }
82
83 } // namespace
84
TEST(TraceConfigTest,TraceConfigFromValidLegacyFormat)85 TEST(TraceConfigTest, TraceConfigFromValidLegacyFormat) {
86 // From trace options strings
87 TraceConfig config("", "record-until-full");
88 EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
89 EXPECT_FALSE(config.IsSystraceEnabled());
90 EXPECT_FALSE(config.IsArgumentFilterEnabled());
91 EXPECT_STREQ("record-until-full", config.ToTraceOptionsString().c_str());
92
93 config = TraceConfig("", "record-continuously");
94 EXPECT_EQ(RECORD_CONTINUOUSLY, config.GetTraceRecordMode());
95 EXPECT_FALSE(config.IsSystraceEnabled());
96 EXPECT_FALSE(config.IsArgumentFilterEnabled());
97 EXPECT_STREQ("record-continuously", config.ToTraceOptionsString().c_str());
98
99 config = TraceConfig("", "trace-to-console");
100 EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
101 EXPECT_FALSE(config.IsSystraceEnabled());
102 EXPECT_FALSE(config.IsArgumentFilterEnabled());
103 EXPECT_STREQ("trace-to-console", config.ToTraceOptionsString().c_str());
104
105 config = TraceConfig("", "record-as-much-as-possible");
106 EXPECT_EQ(RECORD_AS_MUCH_AS_POSSIBLE, config.GetTraceRecordMode());
107 EXPECT_FALSE(config.IsSystraceEnabled());
108 EXPECT_FALSE(config.IsArgumentFilterEnabled());
109 EXPECT_STREQ("record-as-much-as-possible",
110 config.ToTraceOptionsString().c_str());
111
112 config = TraceConfig("", "enable-systrace, record-continuously");
113 EXPECT_EQ(RECORD_CONTINUOUSLY, config.GetTraceRecordMode());
114 EXPECT_TRUE(config.IsSystraceEnabled());
115 EXPECT_FALSE(config.IsArgumentFilterEnabled());
116 EXPECT_STREQ("record-continuously,enable-systrace",
117 config.ToTraceOptionsString().c_str());
118
119 config = TraceConfig("", "enable-argument-filter,record-as-much-as-possible");
120 EXPECT_EQ(RECORD_AS_MUCH_AS_POSSIBLE, config.GetTraceRecordMode());
121 EXPECT_FALSE(config.IsSystraceEnabled());
122 EXPECT_TRUE(config.IsArgumentFilterEnabled());
123 EXPECT_STREQ("record-as-much-as-possible,enable-argument-filter",
124 config.ToTraceOptionsString().c_str());
125
126 config = TraceConfig(
127 "",
128 "enable-systrace,trace-to-console,enable-argument-filter");
129 EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
130 EXPECT_TRUE(config.IsSystraceEnabled());
131 EXPECT_TRUE(config.IsArgumentFilterEnabled());
132 EXPECT_STREQ(
133 "trace-to-console,enable-systrace,enable-argument-filter",
134 config.ToTraceOptionsString().c_str());
135
136 config = TraceConfig(
137 "", "record-continuously, record-until-full, trace-to-console");
138 EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
139 EXPECT_FALSE(config.IsSystraceEnabled());
140 EXPECT_FALSE(config.IsArgumentFilterEnabled());
141 EXPECT_STREQ("trace-to-console", config.ToTraceOptionsString().c_str());
142
143 // From TraceRecordMode
144 config = TraceConfig("", RECORD_UNTIL_FULL);
145 EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
146 EXPECT_FALSE(config.IsSystraceEnabled());
147 EXPECT_FALSE(config.IsArgumentFilterEnabled());
148 EXPECT_STREQ("record-until-full", config.ToTraceOptionsString().c_str());
149
150 config = TraceConfig("", RECORD_CONTINUOUSLY);
151 EXPECT_EQ(RECORD_CONTINUOUSLY, config.GetTraceRecordMode());
152 EXPECT_FALSE(config.IsSystraceEnabled());
153 EXPECT_FALSE(config.IsArgumentFilterEnabled());
154 EXPECT_STREQ("record-continuously", config.ToTraceOptionsString().c_str());
155
156 config = TraceConfig("", ECHO_TO_CONSOLE);
157 EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
158 EXPECT_FALSE(config.IsSystraceEnabled());
159 EXPECT_FALSE(config.IsArgumentFilterEnabled());
160 EXPECT_STREQ("trace-to-console", config.ToTraceOptionsString().c_str());
161
162 config = TraceConfig("", RECORD_AS_MUCH_AS_POSSIBLE);
163 EXPECT_EQ(RECORD_AS_MUCH_AS_POSSIBLE, config.GetTraceRecordMode());
164 EXPECT_FALSE(config.IsSystraceEnabled());
165 EXPECT_FALSE(config.IsArgumentFilterEnabled());
166 EXPECT_STREQ("record-as-much-as-possible",
167 config.ToTraceOptionsString().c_str());
168
169 // From category filter strings
170 config = TraceConfig("included,-excluded,inc_pattern*,-exc_pattern*", "");
171 EXPECT_STREQ("included,inc_pattern*,-excluded,-exc_pattern*",
172 config.ToCategoryFilterString().c_str());
173
174 config = TraceConfig("only_inc_cat", "");
175 EXPECT_STREQ("only_inc_cat", config.ToCategoryFilterString().c_str());
176
177 config = TraceConfig("-only_exc_cat", "");
178 EXPECT_STREQ("-only_exc_cat", config.ToCategoryFilterString().c_str());
179
180 config = TraceConfig("disabled-by-default-cc,-excluded", "");
181 EXPECT_STREQ("disabled-by-default-cc,-excluded",
182 config.ToCategoryFilterString().c_str());
183
184 config = TraceConfig("disabled-by-default-cc,included", "");
185 EXPECT_STREQ("included,disabled-by-default-cc",
186 config.ToCategoryFilterString().c_str());
187
188 // From both trace options and category filter strings
189 config = TraceConfig("", "");
190 EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
191 EXPECT_FALSE(config.IsSystraceEnabled());
192 EXPECT_FALSE(config.IsArgumentFilterEnabled());
193 EXPECT_STREQ("", config.ToCategoryFilterString().c_str());
194 EXPECT_STREQ("record-until-full", config.ToTraceOptionsString().c_str());
195
196 config = TraceConfig("included,-excluded,inc_pattern*,-exc_pattern*",
197 "enable-systrace, trace-to-console");
198 EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
199 EXPECT_TRUE(config.IsSystraceEnabled());
200 EXPECT_FALSE(config.IsArgumentFilterEnabled());
201 EXPECT_STREQ("included,inc_pattern*,-excluded,-exc_pattern*",
202 config.ToCategoryFilterString().c_str());
203 EXPECT_STREQ("trace-to-console,enable-systrace",
204 config.ToTraceOptionsString().c_str());
205
206 // From both trace options and category filter strings with spaces.
207 config = TraceConfig(" included , -excluded, inc_pattern*, ,-exc_pattern* ",
208 "enable-systrace, ,trace-to-console ");
209 EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
210 EXPECT_TRUE(config.IsSystraceEnabled());
211 EXPECT_FALSE(config.IsArgumentFilterEnabled());
212 EXPECT_STREQ("included,inc_pattern*,-excluded,-exc_pattern*",
213 config.ToCategoryFilterString().c_str());
214 EXPECT_STREQ("trace-to-console,enable-systrace",
215 config.ToTraceOptionsString().c_str());
216
217 // From category filter string and TraceRecordMode
218 config = TraceConfig("included,-excluded,inc_pattern*,-exc_pattern*",
219 RECORD_CONTINUOUSLY);
220 EXPECT_EQ(RECORD_CONTINUOUSLY, config.GetTraceRecordMode());
221 EXPECT_FALSE(config.IsSystraceEnabled());
222 EXPECT_FALSE(config.IsArgumentFilterEnabled());
223 EXPECT_STREQ("included,inc_pattern*,-excluded,-exc_pattern*",
224 config.ToCategoryFilterString().c_str());
225 EXPECT_STREQ("record-continuously", config.ToTraceOptionsString().c_str());
226 }
227
TEST(TraceConfigTest,TraceConfigFromInvalidLegacyStrings)228 TEST(TraceConfigTest, TraceConfigFromInvalidLegacyStrings) {
229 TraceConfig config("", "foo-bar-baz");
230 EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
231 EXPECT_FALSE(config.IsSystraceEnabled());
232 EXPECT_FALSE(config.IsArgumentFilterEnabled());
233 EXPECT_STREQ("", config.ToCategoryFilterString().c_str());
234 EXPECT_STREQ("record-until-full", config.ToTraceOptionsString().c_str());
235
236 config = TraceConfig("arbitrary-category", "foo-bar-baz, enable-systrace");
237 EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
238 EXPECT_TRUE(config.IsSystraceEnabled());
239 EXPECT_FALSE(config.IsArgumentFilterEnabled());
240 EXPECT_STREQ("arbitrary-category", config.ToCategoryFilterString().c_str());
241 EXPECT_STREQ("record-until-full,enable-systrace",
242 config.ToTraceOptionsString().c_str());
243 }
244
TEST(TraceConfigTest,ConstructDefaultTraceConfig)245 TEST(TraceConfigTest, ConstructDefaultTraceConfig) {
246 TraceConfig tc;
247 EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
248 EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
249 CheckDefaultTraceConfigBehavior(tc);
250
251 // Constructors from category filter string and trace option string.
252 TraceConfig tc_asterisk("*", "");
253 EXPECT_STREQ("*", tc_asterisk.ToCategoryFilterString().c_str());
254 CheckDefaultTraceConfigBehavior(tc_asterisk);
255
256 TraceConfig tc_empty_category_filter("", "");
257 EXPECT_STREQ("", tc_empty_category_filter.ToCategoryFilterString().c_str());
258 EXPECT_STREQ(kDefaultTraceConfigString,
259 tc_empty_category_filter.ToString().c_str());
260 CheckDefaultTraceConfigBehavior(tc_empty_category_filter);
261
262 // Constructor from JSON formated config string.
263 TraceConfig tc_empty_json_string("");
264 EXPECT_STREQ("", tc_empty_json_string.ToCategoryFilterString().c_str());
265 EXPECT_STREQ(kDefaultTraceConfigString,
266 tc_empty_json_string.ToString().c_str());
267 CheckDefaultTraceConfigBehavior(tc_empty_json_string);
268
269 // Constructor from dictionary value.
270 DictionaryValue dict;
271 TraceConfig tc_dict(dict);
272 EXPECT_STREQ("", tc_dict.ToCategoryFilterString().c_str());
273 EXPECT_STREQ(kDefaultTraceConfigString, tc_dict.ToString().c_str());
274 CheckDefaultTraceConfigBehavior(tc_dict);
275 }
276
TEST(TraceConfigTest,EmptyAndAsteriskCategoryFilterString)277 TEST(TraceConfigTest, EmptyAndAsteriskCategoryFilterString) {
278 TraceConfig tc_empty("", "");
279 TraceConfig tc_asterisk("*", "");
280
281 EXPECT_STREQ("", tc_empty.ToCategoryFilterString().c_str());
282 EXPECT_STREQ("*", tc_asterisk.ToCategoryFilterString().c_str());
283
284 // Both fall back to default config.
285 CheckDefaultTraceConfigBehavior(tc_empty);
286 CheckDefaultTraceConfigBehavior(tc_asterisk);
287
288 // They differ only for internal checking.
289 EXPECT_FALSE(tc_empty.category_filter().IsCategoryEnabled("Category1"));
290 EXPECT_FALSE(
291 tc_empty.category_filter().IsCategoryEnabled("not-excluded-category"));
292 EXPECT_TRUE(tc_asterisk.category_filter().IsCategoryEnabled("Category1"));
293 EXPECT_TRUE(
294 tc_asterisk.category_filter().IsCategoryEnabled("not-excluded-category"));
295 }
296
TEST(TraceConfigTest,DisabledByDefaultCategoryFilterString)297 TEST(TraceConfigTest, DisabledByDefaultCategoryFilterString) {
298 TraceConfig tc("foo,disabled-by-default-foo", "");
299 EXPECT_STREQ("foo,disabled-by-default-foo",
300 tc.ToCategoryFilterString().c_str());
301 EXPECT_TRUE(tc.IsCategoryGroupEnabled("foo"));
302 EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-foo"));
303 EXPECT_FALSE(tc.IsCategoryGroupEnabled("bar"));
304 EXPECT_FALSE(tc.IsCategoryGroupEnabled("disabled-by-default-bar"));
305
306 EXPECT_TRUE(tc.event_filters().empty());
307 // Enabling only the disabled-by-default-* category means the default ones
308 // are also enabled.
309 tc = TraceConfig("disabled-by-default-foo", "");
310 EXPECT_STREQ("disabled-by-default-foo", tc.ToCategoryFilterString().c_str());
311 EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-foo"));
312 EXPECT_TRUE(tc.IsCategoryGroupEnabled("foo"));
313 EXPECT_TRUE(tc.IsCategoryGroupEnabled("bar"));
314 EXPECT_FALSE(tc.IsCategoryGroupEnabled("disabled-by-default-bar"));
315 }
316
TEST(TraceConfigTest,TraceConfigFromDict)317 TEST(TraceConfigTest, TraceConfigFromDict) {
318 // Passing in empty dictionary will result in default trace config.
319 DictionaryValue dict;
320 TraceConfig tc(dict);
321 EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
322 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
323 EXPECT_FALSE(tc.IsSystraceEnabled());
324 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
325 EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
326
327 std::unique_ptr<Value> default_value(
328 JSONReader::Read(kDefaultTraceConfigString));
329 DCHECK(default_value);
330 const DictionaryValue* default_dict = nullptr;
331 bool is_dict = default_value->GetAsDictionary(&default_dict);
332 DCHECK(is_dict);
333 TraceConfig default_tc(*default_dict);
334 EXPECT_STREQ(kDefaultTraceConfigString, default_tc.ToString().c_str());
335 EXPECT_EQ(RECORD_UNTIL_FULL, default_tc.GetTraceRecordMode());
336 EXPECT_FALSE(default_tc.IsSystraceEnabled());
337 EXPECT_FALSE(default_tc.IsArgumentFilterEnabled());
338 EXPECT_STREQ("", default_tc.ToCategoryFilterString().c_str());
339
340 std::unique_ptr<Value> custom_value(
341 JSONReader::Read(kCustomTraceConfigString));
342 DCHECK(custom_value);
343 const DictionaryValue* custom_dict = nullptr;
344 is_dict = custom_value->GetAsDictionary(&custom_dict);
345 DCHECK(is_dict);
346 TraceConfig custom_tc(*custom_dict);
347 EXPECT_STREQ(kCustomTraceConfigString, custom_tc.ToString().c_str());
348 EXPECT_EQ(RECORD_CONTINUOUSLY, custom_tc.GetTraceRecordMode());
349 EXPECT_TRUE(custom_tc.IsSystraceEnabled());
350 EXPECT_TRUE(custom_tc.IsArgumentFilterEnabled());
351 EXPECT_STREQ(
352 "included,inc_pattern*,"
353 "disabled-by-default-cc,disabled-by-default-memory-infra,"
354 "-excluded,-exc_pattern*",
355 custom_tc.ToCategoryFilterString().c_str());
356 }
357
TEST(TraceConfigTest,TraceConfigFromValidString)358 TEST(TraceConfigTest, TraceConfigFromValidString) {
359 // Using some non-empty config string.
360 const char config_string[] =
361 "{"
362 "\"enable_argument_filter\":true,"
363 "\"enable_systrace\":true,"
364 "\"event_filters\":["
365 "{"
366 "\"excluded_categories\":[\"unfiltered_cat\"],"
367 "\"filter_args\":{\"event_name_whitelist\":[\"a snake\",\"a dog\"]},"
368 "\"filter_predicate\":\"event_whitelist_predicate\","
369 "\"included_categories\":[\"*\"]"
370 "}"
371 "],"
372 "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
373 "\"included_categories\":[\"included\","
374 "\"inc_pattern*\","
375 "\"disabled-by-default-cc\"],"
376 "\"record_mode\":\"record-continuously\""
377 "}";
378 TraceConfig tc(config_string);
379
380 EXPECT_STREQ(config_string, tc.ToString().c_str());
381 EXPECT_EQ(RECORD_CONTINUOUSLY, tc.GetTraceRecordMode());
382 EXPECT_TRUE(tc.IsSystraceEnabled());
383 EXPECT_TRUE(tc.IsArgumentFilterEnabled());
384 EXPECT_STREQ(
385 "included,inc_pattern*,disabled-by-default-cc,-excluded,"
386 "-exc_pattern*",
387 tc.ToCategoryFilterString().c_str());
388
389 EXPECT_TRUE(tc.category_filter().IsCategoryEnabled("included"));
390 EXPECT_TRUE(tc.category_filter().IsCategoryEnabled("inc_pattern_category"));
391 EXPECT_TRUE(tc.category_filter().IsCategoryEnabled("disabled-by-default-cc"));
392 EXPECT_FALSE(tc.category_filter().IsCategoryEnabled("excluded"));
393 EXPECT_FALSE(tc.category_filter().IsCategoryEnabled("exc_pattern_category"));
394 EXPECT_FALSE(
395 tc.category_filter().IsCategoryEnabled("disabled-by-default-others"));
396 EXPECT_FALSE(
397 tc.category_filter().IsCategoryEnabled("not-excluded-nor-included"));
398
399 EXPECT_TRUE(tc.IsCategoryGroupEnabled("included"));
400 EXPECT_TRUE(tc.IsCategoryGroupEnabled("inc_pattern_category"));
401 EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-cc"));
402 EXPECT_FALSE(tc.IsCategoryGroupEnabled("excluded"));
403 EXPECT_FALSE(tc.IsCategoryGroupEnabled("exc_pattern_category"));
404 EXPECT_FALSE(tc.IsCategoryGroupEnabled("disabled-by-default-others"));
405 EXPECT_FALSE(tc.IsCategoryGroupEnabled("not-excluded-nor-included"));
406
407 EXPECT_TRUE(tc.IsCategoryGroupEnabled("included,excluded"));
408 EXPECT_FALSE(tc.IsCategoryGroupEnabled("excluded,exc_pattern_category"));
409 EXPECT_TRUE(tc.IsCategoryGroupEnabled("included"));
410
411 EXPECT_EQ(tc.event_filters().size(), 1u);
412 const TraceConfig::EventFilterConfig& event_filter = tc.event_filters()[0];
413 EXPECT_STREQ("event_whitelist_predicate",
414 event_filter.predicate_name().c_str());
415 EXPECT_EQ(1u, event_filter.category_filter().included_categories().size());
416 EXPECT_STREQ("*",
417 event_filter.category_filter().included_categories()[0].c_str());
418 EXPECT_EQ(1u, event_filter.category_filter().excluded_categories().size());
419 EXPECT_STREQ("unfiltered_cat",
420 event_filter.category_filter().excluded_categories()[0].c_str());
421 EXPECT_TRUE(event_filter.filter_args());
422
423 std::string json_out;
424 base::JSONWriter::Write(*event_filter.filter_args(), &json_out);
425 EXPECT_STREQ(json_out.c_str(),
426 "{\"event_name_whitelist\":[\"a snake\",\"a dog\"]}");
427 std::unordered_set<std::string> filter_values;
428 EXPECT_TRUE(event_filter.GetArgAsSet("event_name_whitelist", &filter_values));
429 EXPECT_EQ(2u, filter_values.size());
430 EXPECT_EQ(1u, filter_values.count("a snake"));
431 EXPECT_EQ(1u, filter_values.count("a dog"));
432
433 const char config_string_2[] = "{\"included_categories\":[\"*\"]}";
434 TraceConfig tc2(config_string_2);
435 EXPECT_TRUE(tc2.category_filter().IsCategoryEnabled(
436 "non-disabled-by-default-pattern"));
437 EXPECT_FALSE(
438 tc2.category_filter().IsCategoryEnabled("disabled-by-default-pattern"));
439 EXPECT_TRUE(tc2.IsCategoryGroupEnabled("non-disabled-by-default-pattern"));
440 EXPECT_FALSE(tc2.IsCategoryGroupEnabled("disabled-by-default-pattern"));
441
442 // Clear
443 tc.Clear();
444 EXPECT_STREQ(tc.ToString().c_str(),
445 "{"
446 "\"enable_argument_filter\":false,"
447 "\"enable_systrace\":false,"
448 "\"record_mode\":\"record-until-full\""
449 "}");
450 }
451
TEST(TraceConfigTest,TraceConfigFromInvalidString)452 TEST(TraceConfigTest, TraceConfigFromInvalidString) {
453 // The config string needs to be a dictionary correctly formatted as a JSON
454 // string. Otherwise, it will fall back to the default initialization.
455 TraceConfig tc("");
456 EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
457 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
458 EXPECT_FALSE(tc.IsSystraceEnabled());
459 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
460 EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
461 CheckDefaultTraceConfigBehavior(tc);
462
463 tc = TraceConfig("This is an invalid config string.");
464 EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
465 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
466 EXPECT_FALSE(tc.IsSystraceEnabled());
467 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
468 EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
469 CheckDefaultTraceConfigBehavior(tc);
470
471 tc = TraceConfig("[\"This\", \"is\", \"not\", \"a\", \"dictionary\"]");
472 EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
473 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
474 EXPECT_FALSE(tc.IsSystraceEnabled());
475 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
476 EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
477 CheckDefaultTraceConfigBehavior(tc);
478
479 tc = TraceConfig("{\"record_mode\": invalid-value-needs-double-quote}");
480 EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
481 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
482 EXPECT_FALSE(tc.IsSystraceEnabled());
483 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
484 EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
485 CheckDefaultTraceConfigBehavior(tc);
486
487 // If the config string a dictionary formatted as a JSON string, it will
488 // initialize TraceConfig with best effort.
489 tc = TraceConfig("{}");
490 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
491 EXPECT_FALSE(tc.IsSystraceEnabled());
492 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
493 EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
494 CheckDefaultTraceConfigBehavior(tc);
495
496 tc = TraceConfig("{\"arbitrary-key\":\"arbitrary-value\"}");
497 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
498 EXPECT_FALSE(tc.IsSystraceEnabled());
499 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
500 EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
501 CheckDefaultTraceConfigBehavior(tc);
502
503 const char invalid_config_string[] =
504 "{"
505 "\"enable_systrace\":1,"
506 "\"excluded_categories\":[\"excluded\"],"
507 "\"included_categories\":\"not a list\","
508 "\"record_mode\":\"arbitrary-mode\""
509 "}";
510 tc = TraceConfig(invalid_config_string);
511 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
512 EXPECT_FALSE(tc.IsSystraceEnabled());
513 EXPECT_FALSE(tc.IsArgumentFilterEnabled());
514
515 const char invalid_config_string_2[] =
516 "{"
517 "\"included_categories\":[\"category\",\"disabled-by-default-pattern\"],"
518 "\"excluded_categories\":[\"category\",\"disabled-by-default-pattern\"]"
519 "}";
520 tc = TraceConfig(invalid_config_string_2);
521 EXPECT_TRUE(tc.category_filter().IsCategoryEnabled("category"));
522 EXPECT_TRUE(
523 tc.category_filter().IsCategoryEnabled("disabled-by-default-pattern"));
524 EXPECT_TRUE(tc.IsCategoryGroupEnabled("category"));
525 EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-pattern"));
526 }
527
TEST(TraceConfigTest,MergingTraceConfigs)528 TEST(TraceConfigTest, MergingTraceConfigs) {
529 // Merge
530 TraceConfig tc;
531 TraceConfig tc2("included,-excluded,inc_pattern*,-exc_pattern*", "");
532 tc.Merge(tc2);
533 EXPECT_STREQ("{"
534 "\"enable_argument_filter\":false,"
535 "\"enable_systrace\":false,"
536 "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
537 "\"record_mode\":\"record-until-full\""
538 "}",
539 tc.ToString().c_str());
540 }
541
TEST(TraceConfigTest,IsCategoryGroupEnabled)542 TEST(TraceConfigTest, IsCategoryGroupEnabled) {
543 // Enabling a disabled- category does not require all categories to be traced
544 // to be included.
545 TraceConfig tc("disabled-by-default-cc,-excluded", "");
546 EXPECT_STREQ("disabled-by-default-cc,-excluded",
547 tc.ToCategoryFilterString().c_str());
548 EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-cc"));
549 EXPECT_TRUE(tc.IsCategoryGroupEnabled("some_other_group"));
550 EXPECT_FALSE(tc.IsCategoryGroupEnabled("excluded"));
551
552 // Enabled a disabled- category and also including makes all categories to
553 // be traced require including.
554 tc = TraceConfig("disabled-by-default-cc,included", "");
555 EXPECT_STREQ("included,disabled-by-default-cc",
556 tc.ToCategoryFilterString().c_str());
557 EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-cc"));
558 EXPECT_TRUE(tc.IsCategoryGroupEnabled("included"));
559 EXPECT_FALSE(tc.IsCategoryGroupEnabled("other_included"));
560
561 // Excluding categories won't enable disabled-by-default ones with the
562 // excluded category is also present in the group.
563 tc = TraceConfig("-excluded", "");
564 EXPECT_STREQ("-excluded", tc.ToCategoryFilterString().c_str());
565 EXPECT_FALSE(tc.IsCategoryGroupEnabled("excluded,disabled-by-default-cc"));
566 }
567
TEST(TraceConfigTest,IsCategoryNameAllowed)568 TEST(TraceConfigTest, IsCategoryNameAllowed) {
569 // Test that IsCategoryNameAllowed actually catches categories that are
570 // explicitly forbidden. This method is called in a DCHECK to assert that we
571 // don't have these types of strings as categories.
572 EXPECT_FALSE(
573 TraceConfigCategoryFilter::IsCategoryNameAllowed(" bad_category "));
574 EXPECT_FALSE(
575 TraceConfigCategoryFilter::IsCategoryNameAllowed(" bad_category"));
576 EXPECT_FALSE(
577 TraceConfigCategoryFilter::IsCategoryNameAllowed("bad_category "));
578 EXPECT_FALSE(
579 TraceConfigCategoryFilter::IsCategoryNameAllowed(" bad_category"));
580 EXPECT_FALSE(
581 TraceConfigCategoryFilter::IsCategoryNameAllowed("bad_category "));
582 EXPECT_FALSE(
583 TraceConfigCategoryFilter::IsCategoryNameAllowed(" bad_category "));
584 EXPECT_FALSE(TraceConfigCategoryFilter::IsCategoryNameAllowed(""));
585 EXPECT_TRUE(
586 TraceConfigCategoryFilter::IsCategoryNameAllowed("good_category"));
587 }
588
TEST(TraceConfigTest,SetTraceOptionValues)589 TEST(TraceConfigTest, SetTraceOptionValues) {
590 TraceConfig tc;
591 EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
592 EXPECT_FALSE(tc.IsSystraceEnabled());
593
594 tc.SetTraceRecordMode(RECORD_AS_MUCH_AS_POSSIBLE);
595 EXPECT_EQ(RECORD_AS_MUCH_AS_POSSIBLE, tc.GetTraceRecordMode());
596
597 tc.EnableSystrace();
598 EXPECT_TRUE(tc.IsSystraceEnabled());
599 }
600
TEST(TraceConfigTest,TraceConfigFromMemoryConfigString)601 TEST(TraceConfigTest, TraceConfigFromMemoryConfigString) {
602 std::string tc_str1 =
603 TraceConfigMemoryTestUtil::GetTraceConfig_PeriodicTriggers(200, 2000);
604 TraceConfig tc1(tc_str1);
605 EXPECT_EQ(tc_str1, tc1.ToString());
606 TraceConfig tc2(
607 TraceConfigMemoryTestUtil::GetTraceConfig_LegacyPeriodicTriggers(200,
608 2000));
609 EXPECT_EQ(tc_str1, tc2.ToString());
610
611 EXPECT_TRUE(tc1.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
612 ASSERT_EQ(2u, tc1.memory_dump_config().triggers.size());
613
614 EXPECT_EQ(200u,
615 tc1.memory_dump_config().triggers[0].min_time_between_dumps_ms);
616 EXPECT_EQ(MemoryDumpLevelOfDetail::LIGHT,
617 tc1.memory_dump_config().triggers[0].level_of_detail);
618
619 EXPECT_EQ(2000u,
620 tc1.memory_dump_config().triggers[1].min_time_between_dumps_ms);
621 EXPECT_EQ(MemoryDumpLevelOfDetail::DETAILED,
622 tc1.memory_dump_config().triggers[1].level_of_detail);
623 EXPECT_EQ(
624 2048u,
625 tc1.memory_dump_config().heap_profiler_options.breakdown_threshold_bytes);
626
627 std::string tc_str3 =
628 TraceConfigMemoryTestUtil::GetTraceConfig_BackgroundTrigger(
629 1 /* period_ms */);
630 TraceConfig tc3(tc_str3);
631 EXPECT_EQ(tc_str3, tc3.ToString());
632 EXPECT_TRUE(tc3.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
633 ASSERT_EQ(1u, tc3.memory_dump_config().triggers.size());
634 EXPECT_EQ(1u, tc3.memory_dump_config().triggers[0].min_time_between_dumps_ms);
635 EXPECT_EQ(MemoryDumpLevelOfDetail::BACKGROUND,
636 tc3.memory_dump_config().triggers[0].level_of_detail);
637 }
638
TEST(TraceConfigTest,EmptyMemoryDumpConfigTest)639 TEST(TraceConfigTest, EmptyMemoryDumpConfigTest) {
640 // Empty trigger list should also be specified when converting back to string.
641 TraceConfig tc(TraceConfigMemoryTestUtil::GetTraceConfig_EmptyTriggers());
642 EXPECT_EQ(TraceConfigMemoryTestUtil::GetTraceConfig_EmptyTriggers(),
643 tc.ToString());
644 EXPECT_EQ(0u, tc.memory_dump_config().triggers.size());
645 EXPECT_EQ(
646 static_cast<uint32_t>(TraceConfig::MemoryDumpConfig::HeapProfiler::
647 kDefaultBreakdownThresholdBytes),
648 tc.memory_dump_config().heap_profiler_options.breakdown_threshold_bytes);
649 }
650
TEST(TraceConfigTest,LegacyStringToMemoryDumpConfig)651 TEST(TraceConfigTest, LegacyStringToMemoryDumpConfig) {
652 TraceConfig tc(MemoryDumpManager::kTraceCategory, "");
653 EXPECT_TRUE(tc.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
654 EXPECT_NE(std::string::npos, tc.ToString().find("memory_dump_config"));
655 EXPECT_EQ(0u, tc.memory_dump_config().triggers.size());
656 EXPECT_EQ(
657 static_cast<uint32_t>(TraceConfig::MemoryDumpConfig::HeapProfiler::
658 kDefaultBreakdownThresholdBytes),
659 tc.memory_dump_config().heap_profiler_options.breakdown_threshold_bytes);
660 }
661
662 } // namespace trace_event
663 } // namespace base
664