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