trace_tests.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. #include <library/cpp/lwtrace/all.h>
  2. #include <library/cpp/getopt/last_getopt.h>
  3. #include <google/protobuf/text_format.h>
  4. #include <util/system/pipe.h>
  5. #include <util/generic/ymath.h>
  6. #include <util/string/printf.h>
  7. #include <util/string/vector.h>
  8. #define LWTRACE_TESTS_PROVIDER(PROBE, EVENT, GROUPS, TYPES, NAMES) \
  9. PROBE(Simplest, GROUPS("Group"), TYPES(), NAMES()) \
  10. PROBE(IntParam, GROUPS("Group"), TYPES(ui32), NAMES("value")) \
  11. PROBE(StringParam, GROUPS("Group"), TYPES(TString), NAMES("value")) \
  12. PROBE(SymbolParam, GROUPS("Group"), TYPES(NLWTrace::TSymbol), NAMES("symbol")) \
  13. PROBE(CheckParam, GROUPS("Group"), TYPES(NLWTrace::TCheck), NAMES("value")) \
  14. EVENT(TwoParamsEvent, GROUPS("Group"), TYPES(int, TString), NAMES("param1", "param2")) \
  15. EVENT(TwoParamsCheckEvent, GROUPS("Group"), TYPES(NLWTrace::TCheck, TString), NAMES("param1", "param2")) \
  16. /**/
  17. LWTRACE_DECLARE_PROVIDER(LWTRACE_TESTS_PROVIDER)
  18. LWTRACE_DEFINE_PROVIDER(LWTRACE_TESTS_PROVIDER)
  19. LWTRACE_USING(LWTRACE_TESTS_PROVIDER)
  20. namespace NLWTrace {
  21. namespace NTests {
  22. TString gStrValue = "a long string value that can be possible passed as a trace probe string parameter";
  23. //TString gStrValue = "short";
  24. LWTRACE_DEFINE_SYMBOL(gSymbol, "a long symbol value that can be possible passed as a trace probe string parameter");
  25. struct TConfig {
  26. size_t Cycles;
  27. size_t Runs;
  28. bool UnsafeLWTrace;
  29. TConfig() {
  30. Cycles = 100000;
  31. Runs = 10;
  32. UnsafeLWTrace = false;
  33. }
  34. };
  35. struct TMeasure {
  36. double Average;
  37. double Sigma;
  38. TMeasure(double a, double s)
  39. : Average(a)
  40. , Sigma(s)
  41. {
  42. }
  43. };
  44. #define DEFINE_MEASUREMENT(name, ...) \
  45. double name##OneRun(const TConfig& cfg) { \
  46. TInstant t0 = Now(); \
  47. for (size_t i = 0; i < cfg.Cycles; i++) { \
  48. HOTSPOT(name, ##__VA_ARGS__); \
  49. HOTSPOT(name, ##__VA_ARGS__); \
  50. HOTSPOT(name, ##__VA_ARGS__); \
  51. HOTSPOT(name, ##__VA_ARGS__); \
  52. HOTSPOT(name, ##__VA_ARGS__); \
  53. HOTSPOT(name, ##__VA_ARGS__); \
  54. HOTSPOT(name, ##__VA_ARGS__); \
  55. HOTSPOT(name, ##__VA_ARGS__); \
  56. HOTSPOT(name, ##__VA_ARGS__); \
  57. HOTSPOT(name, ##__VA_ARGS__); \
  58. } \
  59. TInstant t1 = Now(); \
  60. return double(t1.MicroSeconds() - t0.MicroSeconds()) / (cfg.Cycles * 10); \
  61. } \
  62. TMeasure name##Time(const TConfig& cfg) { \
  63. double v = 0; \
  64. double vSq = 0; \
  65. for (size_t i = 0; i < cfg.Runs; i++) { \
  66. double value = name##OneRun(cfg); \
  67. v += value; \
  68. vSq += value * value; \
  69. } \
  70. v /= cfg.Runs; \
  71. vSq /= cfg.Runs; \
  72. return TMeasure(v, sqrt(vSq - v * v)); \
  73. } \
  74. /**/
  75. class TProbes: public TProbeRegistry {
  76. public:
  77. TManager Mngr;
  78. TProbes(bool destructiveActionsAllowed)
  79. : Mngr(*this, destructiveActionsAllowed)
  80. {
  81. AddProbesList(LWTRACE_GET_PROBES(LWTRACE_TESTS_PROVIDER));
  82. }
  83. #define HOTSPOT(name, ...) LWPROBE(name, ##__VA_ARGS__);
  84. DEFINE_MEASUREMENT(Simplest);
  85. DEFINE_MEASUREMENT(IntParam, 123);
  86. DEFINE_MEASUREMENT(StringParam, gStrValue);
  87. DEFINE_MEASUREMENT(SymbolParam, gSymbol);
  88. DEFINE_MEASUREMENT(CheckParam, TCheck(13));
  89. #undef HOTSPOT
  90. };
  91. class TInMemoryLogTest {
  92. public:
  93. TInMemoryLog Log;
  94. TInMemoryLogTest()
  95. : Log(1000)
  96. {
  97. }
  98. #define HOTSPOT(name, ...) LWEVENT(name, Log, true, ##__VA_ARGS__);
  99. DEFINE_MEASUREMENT(TwoParamsEvent, 666, TString("bla-bla-bla"));
  100. #undef HOTSPOT
  101. };
  102. class TInMemoryLogCheckTest {
  103. public:
  104. TInMemoryLog Log;
  105. TInMemoryLogCheckTest()
  106. : Log(1000)
  107. {
  108. }
  109. #define HOTSPOT(name, ...) LWEVENT(name, Log, true, ##__VA_ARGS__);
  110. DEFINE_MEASUREMENT(TwoParamsCheckEvent, TCheck(666), TString("bla-bla-bla"));
  111. #undef HOTSPOT
  112. };
  113. NLWTrace::TQuery MakeQuery(const TString& queryStr) {
  114. NLWTrace::TQuery query;
  115. google::protobuf::TextFormat::ParseFromString(queryStr, &query);
  116. return query;
  117. }
  118. void NoExec(const TConfig& cfg) {
  119. TProbes p(cfg.UnsafeLWTrace);
  120. Cout << "call to probe w/o executor: " << p.SimplestTime(cfg) << Endl;
  121. }
  122. void Log(const TConfig& cfg) {
  123. TProbes p(cfg.UnsafeLWTrace);
  124. p.Mngr.New("test-trace", MakeQuery(
  125. "Blocks {"
  126. " ProbeDesc {"
  127. " Name: \"Simplest\""
  128. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  129. " }"
  130. " Action {"
  131. " LogAction {"
  132. " LogTimestamp: false"
  133. " }"
  134. " }"
  135. "}"));
  136. Cout << "call to probe with logging executor: " << p.SimplestTime(cfg) << Endl;
  137. }
  138. void LogTs(const TConfig& cfg) {
  139. TProbes p(cfg.UnsafeLWTrace);
  140. p.Mngr.New("test-trace", MakeQuery(
  141. "Blocks {"
  142. " ProbeDesc {"
  143. " Name: \"Simplest\""
  144. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  145. " }"
  146. " Action {"
  147. " LogAction {"
  148. " LogTimestamp: true"
  149. " }"
  150. " }"
  151. "}"));
  152. Cout << "call to probe with logging (+timestamp) executor: " << p.SimplestTime(cfg) << Endl;
  153. }
  154. void FalseIntFilter(const TConfig& cfg) {
  155. TProbes p(cfg.UnsafeLWTrace);
  156. p.Mngr.New("test-trace", MakeQuery(
  157. "Blocks {"
  158. " ProbeDesc {"
  159. " Name: \"IntParam\""
  160. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  161. " }"
  162. " Predicate {"
  163. " Operators {"
  164. " Type: OT_GT"
  165. " Argument {"
  166. " Param: \"value\""
  167. " }"
  168. " Argument {"
  169. " Value: \"1000\""
  170. " }"
  171. " }"
  172. " }"
  173. " Action {"
  174. " LogAction {"
  175. " LogTimestamp: false"
  176. " }"
  177. " }"
  178. "}"));
  179. Cout << "call to probe with int filter (always false) executor: " << p.IntParamTime(cfg) << Endl;
  180. }
  181. void LogIntAfterFilter(const TConfig& cfg) {
  182. TProbes p(cfg.UnsafeLWTrace);
  183. p.Mngr.New("test-trace", MakeQuery(
  184. "Blocks {"
  185. " ProbeDesc {"
  186. " Name: \"IntParam\""
  187. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  188. " }"
  189. " Predicate {"
  190. " Operators {"
  191. " Type: OT_GT"
  192. " Argument {"
  193. " Param: \"value\""
  194. " }"
  195. " Argument {"
  196. " Value: \"0\""
  197. " }"
  198. " }"
  199. " }"
  200. " Action {"
  201. " LogAction {"
  202. " LogTimestamp: false"
  203. " }"
  204. " }"
  205. "}"));
  206. Cout << "call to probe with int filter (always true) and log executors: " << p.IntParamTime(cfg) << Endl;
  207. }
  208. void LogInt(const TConfig& cfg) {
  209. TProbes p(cfg.UnsafeLWTrace);
  210. p.Mngr.New("test-trace", MakeQuery(
  211. "Blocks {"
  212. " ProbeDesc {"
  213. " Name: \"IntParam\""
  214. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  215. " }"
  216. " Action {"
  217. " LogAction {"
  218. " LogTimestamp: false"
  219. " }"
  220. " }"
  221. "}"));
  222. Cout << "call to int probe with log executor: " << p.IntParamTime(cfg) << Endl;
  223. }
  224. void FalseStringFilter(const TConfig& cfg) {
  225. TProbes p(cfg.UnsafeLWTrace);
  226. p.Mngr.New("test-trace", MakeQuery(
  227. "Blocks {"
  228. " ProbeDesc {"
  229. " Name: \"StringParam\""
  230. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  231. " }"
  232. " Predicate {"
  233. " Operators {"
  234. " Type: OT_EQ"
  235. " Argument {"
  236. " Param: \"value\""
  237. " }"
  238. " Argument {"
  239. " Value: \"string that never can exist\""
  240. " }"
  241. " }"
  242. " }"
  243. " Action {"
  244. " LogAction {"
  245. " LogTimestamp: false"
  246. " }"
  247. " }"
  248. "}"));
  249. Cout << "call to probe with string filter (always false) executor: " << p.StringParamTime(cfg) << Endl;
  250. }
  251. void FalseStringFilterPartialMatch(const TConfig& cfg) {
  252. TProbes p(cfg.UnsafeLWTrace);
  253. p.Mngr.New("test-trace", MakeQuery(
  254. "Blocks {"
  255. " ProbeDesc {"
  256. " Name: \"StringParam\""
  257. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  258. " }"
  259. " Predicate {"
  260. " Operators {"
  261. " Type: OT_EQ"
  262. " Argument {"
  263. " Param: \"value\""
  264. " }"
  265. " Argument {"
  266. " Value: \"" +
  267. gStrValue + "-not-full-match\""
  268. " }"
  269. " }"
  270. " }"
  271. " Action {"
  272. " LogAction {"
  273. " LogTimestamp: false"
  274. " }"
  275. " }"
  276. "}"));
  277. Cout << "call to probe with string filter (always false) executor: " << p.StringParamTime(cfg) << Endl;
  278. }
  279. void LogStringAfterFilter(const TConfig& cfg) {
  280. TProbes p(cfg.UnsafeLWTrace);
  281. p.Mngr.New("test-trace", MakeQuery(
  282. "Blocks {"
  283. " ProbeDesc {"
  284. " Name: \"StringParam\""
  285. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  286. " }"
  287. " Predicate {"
  288. " Operators {"
  289. " Type: OT_EQ"
  290. " Argument {"
  291. " Param: \"value\""
  292. " }"
  293. " Argument {"
  294. " Value: \"" +
  295. gStrValue + "\""
  296. " }"
  297. " }"
  298. " }"
  299. " Action {"
  300. " LogAction {"
  301. " LogTimestamp: false"
  302. " }"
  303. " }"
  304. "}"));
  305. Cout << "call to probe with string filter (always true) and log executors: " << p.StringParamTime(cfg) << Endl;
  306. }
  307. void LogString(const TConfig& cfg) {
  308. TProbes p(cfg.UnsafeLWTrace);
  309. p.Mngr.New("test-trace", MakeQuery(
  310. "Blocks {"
  311. " ProbeDesc {"
  312. " Name: \"StringParam\""
  313. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  314. " }"
  315. " Action {"
  316. " LogAction {"
  317. " LogTimestamp: false"
  318. " }"
  319. " }"
  320. "}"));
  321. Cout << "call to string probe with log executor: " << p.StringParamTime(cfg) << Endl;
  322. }
  323. void LogSymbol(const TConfig& cfg) {
  324. TProbes p(cfg.UnsafeLWTrace);
  325. p.Mngr.New("test-trace", MakeQuery(
  326. "Blocks {"
  327. " ProbeDesc {"
  328. " Name: \"SymbolParam\""
  329. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  330. " }"
  331. " Action {"
  332. " LogAction {"
  333. " LogTimestamp: false"
  334. " }"
  335. " }"
  336. "}"));
  337. Cout << "call to symbol probe with log executor: " << p.SymbolParamTime(cfg) << Endl;
  338. }
  339. void LogCheck(const TConfig& cfg) {
  340. TProbes p(cfg.UnsafeLWTrace);
  341. p.Mngr.New("test-trace", MakeQuery(
  342. "Blocks {"
  343. " ProbeDesc {"
  344. " Name: \"CheckParam\""
  345. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  346. " }"
  347. " Action {"
  348. " LogAction {"
  349. " LogTimestamp: false"
  350. " }"
  351. " }"
  352. "}"));
  353. Cout << "call to check probe with log executor: " << p.CheckParamTime(cfg) << Endl;
  354. }
  355. void InMemoryLog(const TConfig& cfg) {
  356. TInMemoryLogTest test;
  357. Cout << "log to in-memory log with (int, string) writer: " << test.TwoParamsEventTime(cfg) << Endl;
  358. }
  359. void InMemoryLogCheck(const TConfig& cfg) {
  360. TInMemoryLogCheckTest test;
  361. Cout << "log to in-memory log with (leak-check, string) writer: " << test.TwoParamsCheckEventTime(cfg) << Endl;
  362. }
  363. void MultipleActionsCheck(const TConfig& cfg) {
  364. TProbes p(cfg.UnsafeLWTrace);
  365. p.Mngr.New("test-multipleActions", MakeQuery(
  366. "Blocks {"
  367. " ProbeDesc {"
  368. " Name: \"Simplest\""
  369. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  370. " }"
  371. " Predicate {"
  372. " Operators {"
  373. " Type: OT_LT"
  374. " Argument {"
  375. " Variable: \"counter\""
  376. " }"
  377. " Argument {"
  378. " Value: \"2\""
  379. " }"
  380. " }"
  381. " }"
  382. " Action {"
  383. " StatementAction {"
  384. " Type: ST_INC"
  385. " Argument {"
  386. " Variable: \"counter\""
  387. " }"
  388. " }"
  389. " }"
  390. " Action {"
  391. " StatementAction {"
  392. " Type: ST_DEC"
  393. " Argument {"
  394. " Variable: \"counter\""
  395. " }"
  396. " }"
  397. " }"
  398. " Action {"
  399. " StatementAction {"
  400. " Type: ST_SUB_EQ"
  401. " Argument {"
  402. " Variable: \"counter\""
  403. " }"
  404. " Argument {"
  405. " Value: \"-1\""
  406. " }"
  407. " }"
  408. " }"
  409. " Action {"
  410. " SleepAction {"
  411. " NanoSeconds: 25000000" // 25 ms
  412. " }"
  413. " }"
  414. " Action {"
  415. " SleepAction {"
  416. " NanoSeconds: 25000000" // 25 ms
  417. " }"
  418. " }"
  419. "}"));
  420. TInstant t0 = Now();
  421. for (size_t i = 0; i < 10; i++) {
  422. LWPROBE(Simplest);
  423. }
  424. TInstant t1 = Now();
  425. ui64 duration = (t1.NanoSeconds() - t0.NanoSeconds());
  426. Cout << "multiple sleep tested, expected 100000000 ns, measured " << duration << " ns" << Endl;
  427. }
  428. void SleepCheck(const TConfig& cfg) {
  429. TProbes p(cfg.UnsafeLWTrace);
  430. p.Mngr.New("test-sleep", MakeQuery(
  431. "Blocks {"
  432. " ProbeDesc {"
  433. " Name: \"Simplest\""
  434. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  435. " }"
  436. " Action {"
  437. " SleepAction {"
  438. " NanoSeconds: 100000000" // 100 ms
  439. " }"
  440. " }"
  441. "}"));
  442. TInstant t0 = Now();
  443. for (size_t i = 0; i < 10; i++) {
  444. LWPROBE(Simplest);
  445. }
  446. TInstant t1 = Now();
  447. ui64 duration = (t1.NanoSeconds() - t0.NanoSeconds()) / (ui64)10;
  448. Cout << "sleep tested, expected 100000000 ns, measured " << duration << " ns" << Endl;
  449. }
  450. void KillCheckChild(const TConfig& cfg, TPipeHandle& writer) {
  451. TProbes p(cfg.UnsafeLWTrace);
  452. p.Mngr.New("test-kill", MakeQuery(
  453. "Blocks {"
  454. " ProbeDesc {"
  455. " Name: \"Simplest\""
  456. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  457. " }"
  458. " Action {"
  459. " KillAction {"
  460. " }"
  461. " }"
  462. "}"));
  463. // Send "i'm alive and ok" to the parent (0)
  464. char buffer = 0;
  465. writer.Write(&buffer, 1);
  466. LWPROBE(Simplest);
  467. // Send "i'm alive and that's not OK" to the parent (1)
  468. buffer = 1;
  469. writer.Write(&buffer, 1);
  470. }
  471. void KillCheckParent(TPipeHandle& reader) {
  472. char buffer = -1;
  473. reader.Read(&buffer, 1);
  474. reader.Read(&buffer, 1);
  475. if (buffer == -1)
  476. Cerr << "\t\terror: process died before transfering OK message during the KillAction test!" << Endl;
  477. else if (buffer != 0)
  478. Cerr << "\t\terror: process failed to die on time during the KillAction test!" << Endl;
  479. else
  480. Cout << "\t\tkill executor tested OK." << Endl;
  481. }
  482. void KillCheck(const TConfig& cfg) {
  483. #ifdef _unix_
  484. TPipeHandle reader;
  485. TPipeHandle writer;
  486. TPipeHandle::Pipe(reader, writer);
  487. Cout << "forking the process..." << Endl;
  488. pid_t cpid = fork();
  489. if (cpid == -1) {
  490. Cerr << "\t\terror forking for the KillAction test!" << Endl;
  491. } else if (cpid == 0) {
  492. reader.Close();
  493. KillCheckChild(cfg, writer);
  494. writer.Close();
  495. exit(EXIT_SUCCESS);
  496. } else {
  497. writer.Close();
  498. KillCheckParent(reader);
  499. reader.Close();
  500. }
  501. #else
  502. Cout << "kill action test for windows is not implemented." << Endl;
  503. #endif
  504. }
  505. void LogIntModFilter(const TConfig& cfg) {
  506. TProbes p(cfg.UnsafeLWTrace);
  507. p.Mngr.New("test-trace", MakeQuery(
  508. "Blocks {"
  509. " ProbeDesc {"
  510. " Name: \"IntParam\""
  511. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  512. " }"
  513. " Predicate {"
  514. " Operators {"
  515. " Type: OT_GT"
  516. " Argument {"
  517. " Param: \"value\""
  518. " }"
  519. " Argument {"
  520. " Value: \"0\""
  521. " }"
  522. " }"
  523. " }"
  524. " Action {"
  525. " StatementAction {"
  526. " Type: ST_ADD_EQ"
  527. " Argument {"
  528. " Variable: \"counter\""
  529. " }"
  530. " Argument {"
  531. " Value: \"1\""
  532. " }"
  533. " }"
  534. " }"
  535. " Action {"
  536. " StatementAction {"
  537. " Type: ST_ADD"
  538. " Argument {"
  539. " Variable: \"counter\""
  540. " }"
  541. " Argument {"
  542. " Variable: \"counter\""
  543. " }"
  544. " Argument {"
  545. " Value: \"1\""
  546. " }"
  547. " }"
  548. " }"
  549. " Action {"
  550. " StatementAction {"
  551. " Type: ST_MOD"
  552. " Argument {"
  553. " Variable: \"counter\""
  554. " }"
  555. " Argument {"
  556. " Variable: \"counter\""
  557. " }"
  558. " Argument {"
  559. " Value: \"20\""
  560. " }"
  561. " }"
  562. " }"
  563. "}"
  564. "Blocks {"
  565. " ProbeDesc {"
  566. " Name: \"IntParam\""
  567. " Provider: \"LWTRACE_TESTS_PROVIDER\""
  568. " }"
  569. " Predicate {"
  570. " Operators {"
  571. " Type: OT_EQ"
  572. " Argument {"
  573. " Variable: \"counter\""
  574. " }"
  575. " Argument {"
  576. " Value: \"0\""
  577. " }"
  578. " }"
  579. " Operators {"
  580. " Type: OT_GT"
  581. " Argument {"
  582. " Param: \"value\""
  583. " }"
  584. " Argument {"
  585. " Value: \"0\""
  586. " }"
  587. " }"
  588. " }"
  589. " Action {"
  590. " LogAction {"
  591. " LogTimestamp: false"
  592. " }"
  593. " }"
  594. "}"));
  595. Cout << "call to probe with int mod filter (always true, mod 10) and log executors: " << p.IntParamTime(cfg) << Endl;
  596. }
  597. #define FOR_EACH_TEST() \
  598. FOR_EACH_TEST_MACRO(LogIntModFilter) \
  599. FOR_EACH_TEST_MACRO(SleepCheck) \
  600. FOR_EACH_TEST_MACRO(MultipleActionsCheck) \
  601. FOR_EACH_TEST_MACRO(KillCheck) \
  602. FOR_EACH_TEST_MACRO(InMemoryLog) \
  603. FOR_EACH_TEST_MACRO(InMemoryLogCheck) \
  604. FOR_EACH_TEST_MACRO(NoExec) \
  605. FOR_EACH_TEST_MACRO(Log) \
  606. FOR_EACH_TEST_MACRO(LogTs) \
  607. FOR_EACH_TEST_MACRO(FalseIntFilter) \
  608. FOR_EACH_TEST_MACRO(LogIntAfterFilter) \
  609. FOR_EACH_TEST_MACRO(LogInt) \
  610. FOR_EACH_TEST_MACRO(FalseStringFilter) \
  611. FOR_EACH_TEST_MACRO(FalseStringFilterPartialMatch) \
  612. FOR_EACH_TEST_MACRO(LogStringAfterFilter) \
  613. FOR_EACH_TEST_MACRO(LogString) \
  614. FOR_EACH_TEST_MACRO(LogSymbol) \
  615. FOR_EACH_TEST_MACRO(LogCheck) \
  616. /**/
  617. int Main(int argc, char** argv) {
  618. TConfig cfg;
  619. using namespace NLastGetopt;
  620. TOpts opts = NLastGetopt::TOpts::Default();
  621. opts.AddLongOption('c', "cycles", "cycles count").RequiredArgument("N").DefaultValue(ToString(cfg.Cycles)).StoreResult(&cfg.Cycles);
  622. opts.AddLongOption('r', "runs", "runs count").RequiredArgument("N").DefaultValue(ToString(cfg.Runs)).StoreResult(&cfg.Runs);
  623. opts.AddLongOption('u', "unsafe-lwtrace", "allow destructive actions").OptionalValue(ToString(true)).DefaultValue(ToString(false)).StoreResult(&cfg.UnsafeLWTrace);
  624. opts.AddHelpOption('h');
  625. TOptsParseResult res(&opts, argc, argv);
  626. TVector<TString> tests = res.GetFreeArgs();
  627. if (tests.empty()) {
  628. #define FOR_EACH_TEST_MACRO(t) tests.push_back(#t);
  629. FOR_EACH_TEST()
  630. #undef FOR_EACH_TEST_MACRO
  631. }
  632. for (size_t i = 0; i < tests.size(); i++) {
  633. const TString& test = tests[i];
  634. #define FOR_EACH_TEST_MACRO(t) \
  635. if (test == #t) { \
  636. Cout << #t ": \t"; \
  637. t(cfg); \
  638. }
  639. FOR_EACH_TEST()
  640. #undef FOR_EACH_TEST_MACRO
  641. }
  642. if (TCheck::ObjCount != 0) {
  643. Cout << ">>>>> THERE IS AN OBJECT LEAK <<<<<" << Endl;
  644. Cout << "NLWTrace::TCheck::ObjCount = " << TCheck::ObjCount << Endl;
  645. }
  646. Cout << "Done" << Endl;
  647. return 0;
  648. }
  649. }
  650. }
  651. template <>
  652. void Out<NLWTrace::NTests::TMeasure>(IOutputStream& os, TTypeTraits<NLWTrace::NTests::TMeasure>::TFuncParam measure) {
  653. os << Sprintf("\n\t\t%.6lf +- %.6lf us,\tRPS: %30.3lf (%.1fM)", measure.Average, measure.Sigma, 1000000.0 / measure.Average, 1.0 / measure.Average);
  654. }
  655. int main(int argc, char** argv) {
  656. try {
  657. return NLWTrace::NTests::Main(argc, argv);
  658. } catch (std::exception& e) {
  659. Cerr << e.what() << Endl;
  660. return 1;
  661. } catch (...) {
  662. Cerr << "Unknown error" << Endl;
  663. return 1;
  664. }
  665. }