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