bvar_variable_unittest.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. // Licensed to the Apache Software Foundation (ASF) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The ASF licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. // Date: Fri Jul 24 17:19:40 CST 2015
  18. #include <pthread.h> // pthread_*
  19. #include <cstddef>
  20. #include <memory>
  21. #include <iostream>
  22. #include <sstream>
  23. #include "butil/time.h"
  24. #include "butil/macros.h"
  25. #include "bvar/bvar.h"
  26. #include <gflags/gflags.h>
  27. #include <gtest/gtest.h>
  28. namespace bvar {
  29. DECLARE_bool(bvar_log_dumpped);
  30. }
  31. namespace {
  32. // overloading for operator<< does not work for gflags>=2.1
  33. template <typename T>
  34. std::string vec2string(const std::vector<T>& vec) {
  35. std::ostringstream os;
  36. os << '[';
  37. if (!vec.empty()) {
  38. os << vec[0];
  39. for (size_t i = 1; i < vec.size(); ++i) {
  40. os << ',' << vec[i];
  41. }
  42. }
  43. os << ']';
  44. return os.str();
  45. }
  46. class VariableTest : public testing::Test {
  47. protected:
  48. void SetUp() {
  49. }
  50. void TearDown() {
  51. ASSERT_EQ(0UL, bvar::Variable::count_exposed());
  52. }
  53. };
  54. TEST_F(VariableTest, status) {
  55. bvar::Status<int> st1;
  56. st1.set_value(9);
  57. #ifdef BAIDU_INTERNAL
  58. boost::any v1;
  59. st1.get_value(&v1);
  60. ASSERT_EQ(9, boost::any_cast<int>(v1));
  61. #endif
  62. ASSERT_EQ(0, st1.expose("var1"));
  63. ASSERT_EQ("9", bvar::Variable::describe_exposed("var1"));
  64. std::vector<std::string> vars;
  65. bvar::Variable::list_exposed(&vars);
  66. ASSERT_EQ(1UL, vars.size());
  67. ASSERT_EQ("var1", vars[0]);
  68. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  69. bvar::Status<int> st2;
  70. st2.set_value(10);
  71. ASSERT_EQ(-1, st2.expose("var1"));
  72. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  73. ASSERT_EQ("10", st2.get_description());
  74. ASSERT_EQ("9", bvar::Variable::describe_exposed("var1"));
  75. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  76. ASSERT_TRUE(st1.hide());
  77. ASSERT_EQ(0UL, bvar::Variable::count_exposed());
  78. ASSERT_EQ("", bvar::Variable::describe_exposed("var1"));
  79. ASSERT_EQ(0, st1.expose("var1"));
  80. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  81. ASSERT_EQ("9", bvar::Variable::describe_exposed("var1"));
  82. ASSERT_EQ(0, st2.expose("var2"));
  83. ASSERT_EQ(2UL, bvar::Variable::count_exposed());
  84. ASSERT_EQ("9", bvar::Variable::describe_exposed("var1"));
  85. ASSERT_EQ("10", bvar::Variable::describe_exposed("var2"));
  86. bvar::Variable::list_exposed(&vars);
  87. ASSERT_EQ(2UL, vars.size());
  88. ASSERT_EQ("var1", vars[0]);
  89. ASSERT_EQ("var2", vars[1]);
  90. ASSERT_TRUE(st2.hide());
  91. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  92. ASSERT_EQ("", bvar::Variable::describe_exposed("var2"));
  93. bvar::Variable::list_exposed(&vars);
  94. ASSERT_EQ(1UL, vars.size());
  95. ASSERT_EQ("var1", vars[0]);
  96. ASSERT_EQ(0, st2.expose("Var2 Again"));
  97. ASSERT_EQ("", bvar::Variable::describe_exposed("Var2 Again"));
  98. ASSERT_EQ("10", bvar::Variable::describe_exposed("var2_again"));
  99. bvar::Variable::list_exposed(&vars);
  100. ASSERT_EQ(2UL, vars.size());
  101. ASSERT_EQ("var1", vars[0]);
  102. ASSERT_EQ("var2_again", vars[1]);
  103. ASSERT_EQ(2UL, bvar::Variable::count_exposed());
  104. bvar::Status<int> st3("var3", 11);
  105. ASSERT_EQ("var3", st3.name());
  106. ASSERT_EQ(3UL, bvar::Variable::count_exposed());
  107. ASSERT_EQ("11", bvar::Variable::describe_exposed("var3"));
  108. bvar::Variable::list_exposed(&vars);
  109. ASSERT_EQ(3UL, vars.size());
  110. ASSERT_EQ("var1", vars[0]);
  111. ASSERT_EQ("var3", vars[1]);
  112. ASSERT_EQ("var2_again", vars[2]);
  113. ASSERT_EQ(3UL, bvar::Variable::count_exposed());
  114. bvar::Status<int> st4("var4", 12);
  115. ASSERT_EQ("var4", st4.name());
  116. ASSERT_EQ(4UL, bvar::Variable::count_exposed());
  117. #ifdef BAIDU_INTERNAL
  118. boost::any v4;
  119. st4.get_value(&v4);
  120. ASSERT_EQ(12, boost::any_cast<int>(v4));
  121. #endif
  122. ASSERT_EQ("12", bvar::Variable::describe_exposed("var4"));
  123. bvar::Variable::list_exposed(&vars);
  124. ASSERT_EQ(4UL, vars.size());
  125. ASSERT_EQ("var1", vars[0]);
  126. ASSERT_EQ("var3", vars[1]);
  127. ASSERT_EQ("var4", vars[2]);
  128. ASSERT_EQ("var2_again", vars[3]);
  129. bvar::Status<void*> st5((void*)19UL);
  130. LOG(INFO) << st5;
  131. #ifdef BAIDU_INTERNAL
  132. boost::any v5;
  133. st5.get_value(&v5);
  134. ASSERT_EQ((void*)19UL, boost::any_cast<void*>(v5));
  135. #endif
  136. ASSERT_EQ("0x13", st5.get_description());
  137. }
  138. namespace foo {
  139. namespace bar {
  140. class Apple {};
  141. class BaNaNa {};
  142. class Car_Rot {};
  143. class RPCTest {};
  144. class HELLO {};
  145. }
  146. }
  147. TEST_F(VariableTest, expose) {
  148. bvar::Status<int> c1;
  149. ASSERT_EQ(0, c1.expose_as("foo::bar::Apple", "c1"));
  150. ASSERT_EQ("foo_bar_apple_c1", c1.name());
  151. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  152. ASSERT_EQ(0, c1.expose_as("foo.bar::BaNaNa", "c1"));
  153. ASSERT_EQ("foo_bar_ba_na_na_c1", c1.name());
  154. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  155. ASSERT_EQ(0, c1.expose_as("foo::bar.Car_Rot", "c1"));
  156. ASSERT_EQ("foo_bar_car_rot_c1", c1.name());
  157. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  158. ASSERT_EQ(0, c1.expose_as("foo-bar-RPCTest", "c1"));
  159. ASSERT_EQ("foo_bar_rpctest_c1", c1.name());
  160. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  161. ASSERT_EQ(0, c1.expose_as("foo-bar-HELLO", "c1"));
  162. ASSERT_EQ("foo_bar_hello_c1", c1.name());
  163. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  164. ASSERT_EQ(0, c1.expose("c1"));
  165. ASSERT_EQ("c1", c1.name());
  166. ASSERT_EQ(1UL, bvar::Variable::count_exposed());
  167. }
  168. class MyDumper : public bvar::Dumper {
  169. public:
  170. bool dump(const std::string& name,
  171. const butil::StringPiece& description) {
  172. _list.push_back(std::make_pair(name, description.as_string()));
  173. return true;
  174. }
  175. std::vector<std::pair<std::string, std::string> > _list;
  176. };
  177. int print_int(void*) {
  178. return 5;
  179. }
  180. TEST_F(VariableTest, dump) {
  181. MyDumper d;
  182. // Nothing to dump yet.
  183. bvar::FLAGS_bvar_log_dumpped = true;
  184. ASSERT_EQ(0, bvar::Variable::dump_exposed(&d, NULL));
  185. ASSERT_TRUE(d._list.empty());
  186. bvar::Adder<int> v2("var2");
  187. v2 << 2;
  188. bvar::Status<int> v1("var1", 1);
  189. bvar::Status<int> v1_2("var1", 12);
  190. bvar::Status<int> v3("foo.bar.Apple", "var3", 3);
  191. bvar::Adder<int> v4("foo.bar.BaNaNa", "var4");
  192. v4 << 4;
  193. bvar::BasicPassiveStatus<int> v5(
  194. "foo::bar::Car_Rot", "var5", print_int, NULL);
  195. ASSERT_EQ(5, bvar::Variable::dump_exposed(&d, NULL));
  196. ASSERT_EQ(5UL, d._list.size());
  197. int i = 0;
  198. ASSERT_EQ("foo_bar_apple_var3", d._list[i++ / 2].first);
  199. ASSERT_EQ("3", d._list[i++ / 2].second);
  200. ASSERT_EQ("foo_bar_ba_na_na_var4", d._list[i++ / 2].first);
  201. ASSERT_EQ("4", d._list[i++ / 2].second);
  202. ASSERT_EQ("foo_bar_car_rot_var5", d._list[i++ / 2].first);
  203. ASSERT_EQ("5", d._list[i++ / 2].second);
  204. ASSERT_EQ("var1", d._list[i++ / 2].first);
  205. ASSERT_EQ("1", d._list[i++ / 2].second);
  206. ASSERT_EQ("var2", d._list[i++ / 2].first);
  207. ASSERT_EQ("2", d._list[i++ / 2].second);
  208. d._list.clear();
  209. bvar::DumpOptions opts;
  210. opts.white_wildcards = "foo_bar_*";
  211. opts.black_wildcards = "*var5";
  212. ASSERT_EQ(2, bvar::Variable::dump_exposed(&d, &opts));
  213. ASSERT_EQ(2UL, d._list.size());
  214. i = 0;
  215. ASSERT_EQ("foo_bar_apple_var3", d._list[i++ / 2].first);
  216. ASSERT_EQ("3", d._list[i++ / 2].second);
  217. ASSERT_EQ("foo_bar_ba_na_na_var4", d._list[i++ / 2].first);
  218. ASSERT_EQ("4", d._list[i++ / 2].second);
  219. d._list.clear();
  220. opts = bvar::DumpOptions();
  221. opts.white_wildcards = "*?rot*";
  222. ASSERT_EQ(1, bvar::Variable::dump_exposed(&d, &opts));
  223. ASSERT_EQ(1UL, d._list.size());
  224. i = 0;
  225. ASSERT_EQ("foo_bar_car_rot_var5", d._list[i++ / 2].first);
  226. ASSERT_EQ("5", d._list[i++ / 2].second);
  227. d._list.clear();
  228. opts = bvar::DumpOptions();
  229. opts.white_wildcards = "";
  230. opts.black_wildcards = "var2;var1";
  231. ASSERT_EQ(3, bvar::Variable::dump_exposed(&d, &opts));
  232. ASSERT_EQ(3UL, d._list.size());
  233. i = 0;
  234. ASSERT_EQ("foo_bar_apple_var3", d._list[i++ / 2].first);
  235. ASSERT_EQ("3", d._list[i++ / 2].second);
  236. ASSERT_EQ("foo_bar_ba_na_na_var4", d._list[i++ / 2].first);
  237. ASSERT_EQ("4", d._list[i++ / 2].second);
  238. ASSERT_EQ("foo_bar_car_rot_var5", d._list[i++ / 2].first);
  239. ASSERT_EQ("5", d._list[i++ / 2].second);
  240. d._list.clear();
  241. opts = bvar::DumpOptions();
  242. opts.white_wildcards = "";
  243. opts.black_wildcards = "f?o_b?r_*;not_exist";
  244. ASSERT_EQ(2, bvar::Variable::dump_exposed(&d, &opts));
  245. ASSERT_EQ(2UL, d._list.size());
  246. i = 0;
  247. ASSERT_EQ("var1", d._list[i++ / 2].first);
  248. ASSERT_EQ("1", d._list[i++ / 2].second);
  249. ASSERT_EQ("var2", d._list[i++ / 2].first);
  250. ASSERT_EQ("2", d._list[i++ / 2].second);
  251. d._list.clear();
  252. opts = bvar::DumpOptions();
  253. opts.question_mark = '$';
  254. opts.white_wildcards = "";
  255. opts.black_wildcards = "f$o_b$r_*;not_exist";
  256. ASSERT_EQ(2, bvar::Variable::dump_exposed(&d, &opts));
  257. ASSERT_EQ(2UL, d._list.size());
  258. i = 0;
  259. ASSERT_EQ("var1", d._list[i++ / 2].first);
  260. ASSERT_EQ("1", d._list[i++ / 2].second);
  261. ASSERT_EQ("var2", d._list[i++ / 2].first);
  262. ASSERT_EQ("2", d._list[i++ / 2].second);
  263. d._list.clear();
  264. opts = bvar::DumpOptions();
  265. opts.white_wildcards = "not_exist";
  266. ASSERT_EQ(0, bvar::Variable::dump_exposed(&d, &opts));
  267. ASSERT_EQ(0UL, d._list.size());
  268. d._list.clear();
  269. opts = bvar::DumpOptions();
  270. opts.white_wildcards = "not_exist;f??o_bar*";
  271. ASSERT_EQ(0, bvar::Variable::dump_exposed(&d, &opts));
  272. ASSERT_EQ(0UL, d._list.size());
  273. }
  274. TEST_F(VariableTest, latency_recorder) {
  275. bvar::LatencyRecorder rec;
  276. rec << 1 << 2 << 3;
  277. ASSERT_EQ(3, rec.count());
  278. ASSERT_EQ(-1, rec.expose(""));
  279. ASSERT_EQ(-1, rec.expose("latency"));
  280. ASSERT_EQ(-1, rec.expose("Latency"));
  281. ASSERT_EQ(0, rec.expose("FooBar__latency"));
  282. std::vector<std::string> names;
  283. bvar::Variable::list_exposed(&names);
  284. std::sort(names.begin(), names.end());
  285. ASSERT_EQ(11UL, names.size()) << vec2string(names);
  286. ASSERT_EQ("foo_bar_count", names[0]);
  287. ASSERT_EQ("foo_bar_latency", names[1]);
  288. ASSERT_EQ("foo_bar_latency_80", names[2]);
  289. ASSERT_EQ("foo_bar_latency_90", names[3]);
  290. ASSERT_EQ("foo_bar_latency_99", names[4]);
  291. ASSERT_EQ("foo_bar_latency_999", names[5]);
  292. ASSERT_EQ("foo_bar_latency_9999", names[6]);
  293. ASSERT_EQ("foo_bar_latency_cdf", names[7]);
  294. ASSERT_EQ("foo_bar_latency_percentiles", names[8]);
  295. ASSERT_EQ("foo_bar_max_latency", names[9]);
  296. ASSERT_EQ("foo_bar_qps", names[10]);
  297. ASSERT_EQ(0, rec.expose("ApplePie"));
  298. bvar::Variable::list_exposed(&names);
  299. std::sort(names.begin(), names.end());
  300. ASSERT_EQ(11UL, names.size());
  301. ASSERT_EQ("apple_pie_count", names[0]);
  302. ASSERT_EQ("apple_pie_latency", names[1]);
  303. ASSERT_EQ("apple_pie_latency_80", names[2]);
  304. ASSERT_EQ("apple_pie_latency_90", names[3]);
  305. ASSERT_EQ("apple_pie_latency_99", names[4]);
  306. ASSERT_EQ("apple_pie_latency_999", names[5]);
  307. ASSERT_EQ("apple_pie_latency_9999", names[6]);
  308. ASSERT_EQ("apple_pie_latency_cdf", names[7]);
  309. ASSERT_EQ("apple_pie_latency_percentiles", names[8]);
  310. ASSERT_EQ("apple_pie_max_latency", names[9]);
  311. ASSERT_EQ("apple_pie_qps", names[10]);
  312. ASSERT_EQ(0, rec.expose("BaNaNa::Latency"));
  313. bvar::Variable::list_exposed(&names);
  314. std::sort(names.begin(), names.end());
  315. ASSERT_EQ(11UL, names.size());
  316. ASSERT_EQ("ba_na_na_count", names[0]);
  317. ASSERT_EQ("ba_na_na_latency", names[1]);
  318. ASSERT_EQ("ba_na_na_latency_80", names[2]);
  319. ASSERT_EQ("ba_na_na_latency_90", names[3]);
  320. ASSERT_EQ("ba_na_na_latency_99", names[4]);
  321. ASSERT_EQ("ba_na_na_latency_999", names[5]);
  322. ASSERT_EQ("ba_na_na_latency_9999", names[6]);
  323. ASSERT_EQ("ba_na_na_latency_cdf", names[7]);
  324. ASSERT_EQ("ba_na_na_latency_percentiles", names[8]);
  325. ASSERT_EQ("ba_na_na_max_latency", names[9]);
  326. ASSERT_EQ("ba_na_na_qps", names[10]);
  327. }
  328. TEST_F(VariableTest, recursive_mutex) {
  329. pthread_mutexattr_t attr;
  330. pthread_mutexattr_init(&attr);
  331. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  332. pthread_mutex_t mutex;
  333. pthread_mutex_init(&mutex, &attr);
  334. pthread_mutexattr_destroy(&attr);
  335. butil::Timer timer;
  336. const size_t N = 1000000;
  337. timer.start();
  338. for (size_t i = 0; i < N; ++i) {
  339. BAIDU_SCOPED_LOCK(mutex);
  340. }
  341. timer.stop();
  342. LOG(INFO) << "Each recursive mutex lock/unlock pair take "
  343. << timer.n_elapsed() / N << "ns";
  344. }
  345. } // namespace
  346. int main(int argc, char** argv) {
  347. testing::InitGoogleTest(&argc, argv);
  348. GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true);
  349. return RUN_ALL_TESTS();
  350. }