• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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