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