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