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 14namespace base { 15namespace trace_event { 16 17namespace { 18 19const char kDefaultTraceConfigString[] = 20 "{" 21 "\"enable_argument_filter\":false," 22 "\"enable_sampling\":false," 23 "\"enable_systrace\":false," 24 "\"record_mode\":\"record-until-full\"" 25 "}"; 26 27const 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 51void 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 71TEST(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 242TEST(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 274TEST(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 306TEST(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 324TEST(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 343TEST(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 387TEST(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 455TEST(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 543TEST(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 565TEST(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 591TEST(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 614TEST(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 630TEST(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 661TEST(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 673TEST(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