trace_config_unittest.cc 31 KB

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