singleton_test.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include <gtest/gtest.h>
  4. #include <stdint.h>
  5. #ifdef _WIN32
  6. # include <windows.h>
  7. #else
  8. # include <dlfcn.h>
  9. #endif
  10. #include "component_a.h"
  11. #include "component_b.h"
  12. #include "component_c.h"
  13. #include "component_d.h"
  14. #include "component_e.h"
  15. #include "component_f.h"
  16. #include "opentelemetry/common/key_value_iterable.h"
  17. #include "opentelemetry/nostd/shared_ptr.h"
  18. #include "opentelemetry/nostd/string_view.h"
  19. #include "opentelemetry/trace/default_span.h"
  20. #include "opentelemetry/trace/noop.h"
  21. #include "opentelemetry/trace/provider.h"
  22. #include "opentelemetry/trace/span.h"
  23. #include "opentelemetry/trace/span_context.h"
  24. #include "opentelemetry/trace/span_context_kv_iterable.h"
  25. #include "opentelemetry/trace/span_startoptions.h"
  26. #include "opentelemetry/trace/tracer.h"
  27. #include "opentelemetry/trace/tracer_provider.h"
  28. using namespace opentelemetry;
  29. void do_something()
  30. {
  31. do_something_in_a();
  32. do_something_in_b();
  33. do_something_in_c();
  34. do_something_in_d();
  35. do_something_in_e();
  36. do_something_in_f();
  37. /*
  38. See https://github.com/bazelbuild/bazel/issues/4218
  39. There is no way to set LD_LIBRARY_PATH in bazel,
  40. for dlopen() to find the library.
  41. Verified manually that dlopen("/full/path/to/libcomponent_g.so") works,
  42. and that the test passes in this case.
  43. */
  44. #ifndef BAZEL_BUILD
  45. /* Call do_something_in_g() */
  46. # ifdef _WIN32
  47. HMODULE component_g = LoadLibraryA("component_g.dll");
  48. # elif defined(__APPLE__)
  49. void *component_g = dlopen("libcomponent_g.dylib", RTLD_NOW);
  50. # else
  51. void *component_g = dlopen("libcomponent_g.so", RTLD_NOW);
  52. # endif
  53. EXPECT_NE(component_g, nullptr);
  54. # ifdef _WIN32
  55. auto *func_g = reinterpret_cast<void (*)()>(GetProcAddress(component_g, "do_something_in_g"));
  56. # else
  57. auto *func_g = reinterpret_cast<void (*)()>(dlsym(component_g, "do_something_in_g"));
  58. # endif
  59. EXPECT_NE(func_g, nullptr);
  60. (*func_g)();
  61. # ifdef _WIN32
  62. FreeLibrary(component_g);
  63. # else
  64. dlclose(component_g);
  65. # endif
  66. /* Call do_something_in_h() */
  67. # ifdef _WIN32
  68. HMODULE component_h = LoadLibraryA("component_h.dll");
  69. # elif defined(__APPLE__)
  70. void *component_h = dlopen("libcomponent_h.dylib", RTLD_NOW);
  71. # else
  72. void *component_h = dlopen("libcomponent_h.so", RTLD_NOW);
  73. # endif
  74. EXPECT_NE(component_h, nullptr);
  75. # ifdef _WIN32
  76. auto *func_h = reinterpret_cast<void (*)()>(GetProcAddress(component_h, "do_something_in_h"));
  77. # else
  78. auto *func_h = reinterpret_cast<void (*)()>(dlsym(component_h, "do_something_in_h"));
  79. # endif
  80. EXPECT_NE(func_h, nullptr);
  81. (*func_h)();
  82. # ifdef _WIN32
  83. FreeLibrary(component_h);
  84. # else
  85. dlclose(component_h);
  86. # endif
  87. #endif /* BAZEL_BUILD */
  88. }
  89. int span_a_lib_count = 0;
  90. int span_a_f1_count = 0;
  91. int span_a_f2_count = 0;
  92. int span_b_lib_count = 0;
  93. int span_b_f1_count = 0;
  94. int span_b_f2_count = 0;
  95. int span_c_lib_count = 0;
  96. int span_c_f1_count = 0;
  97. int span_c_f2_count = 0;
  98. int span_d_lib_count = 0;
  99. int span_d_f1_count = 0;
  100. int span_d_f2_count = 0;
  101. int span_e_lib_count = 0;
  102. int span_e_f1_count = 0;
  103. int span_e_f2_count = 0;
  104. int span_f_lib_count = 0;
  105. int span_f_f1_count = 0;
  106. int span_f_f2_count = 0;
  107. int span_g_lib_count = 0;
  108. int span_g_f1_count = 0;
  109. int span_g_f2_count = 0;
  110. int span_h_lib_count = 0;
  111. int span_h_f1_count = 0;
  112. int span_h_f2_count = 0;
  113. int unknown_span_count = 0;
  114. void reset_counts()
  115. {
  116. span_a_lib_count = 0;
  117. span_a_f1_count = 0;
  118. span_a_f2_count = 0;
  119. span_b_lib_count = 0;
  120. span_b_f1_count = 0;
  121. span_b_f2_count = 0;
  122. span_c_lib_count = 0;
  123. span_c_f1_count = 0;
  124. span_c_f2_count = 0;
  125. span_d_lib_count = 0;
  126. span_d_f1_count = 0;
  127. span_d_f2_count = 0;
  128. span_e_lib_count = 0;
  129. span_e_f1_count = 0;
  130. span_e_f2_count = 0;
  131. span_f_lib_count = 0;
  132. span_f_f1_count = 0;
  133. span_f_f2_count = 0;
  134. span_g_lib_count = 0;
  135. span_g_f1_count = 0;
  136. span_g_f2_count = 0;
  137. span_h_lib_count = 0;
  138. span_h_f1_count = 0;
  139. span_h_f2_count = 0;
  140. unknown_span_count = 0;
  141. }
  142. class MyTracer : public trace::Tracer
  143. {
  144. public:
  145. MyTracer()
  146. {
  147. #if OPENTELEMETRY_ABI_VERSION_NO >= 2
  148. UpdateEnabled(true);
  149. #endif
  150. }
  151. nostd::shared_ptr<trace::Span> StartSpan(
  152. nostd::string_view name,
  153. const common::KeyValueIterable & /* attributes */,
  154. const trace::SpanContextKeyValueIterable & /* links */,
  155. const trace::StartSpanOptions & /* options */) noexcept override
  156. {
  157. nostd::shared_ptr<trace::Span> result(new trace::DefaultSpan(trace::SpanContext::GetInvalid()));
  158. /*
  159. Unit test code, no need to be fancy.
  160. */
  161. if (name == "A::library")
  162. {
  163. span_a_lib_count++;
  164. }
  165. else if (name == "A::f1")
  166. {
  167. span_a_f1_count++;
  168. }
  169. else if (name == "A::f2")
  170. {
  171. span_a_f2_count++;
  172. }
  173. else if (name == "B::library")
  174. {
  175. span_b_lib_count++;
  176. }
  177. else if (name == "B::f1")
  178. {
  179. span_b_f1_count++;
  180. }
  181. else if (name == "B::f2")
  182. {
  183. span_b_f2_count++;
  184. }
  185. else if (name == "C::library")
  186. {
  187. span_c_lib_count++;
  188. }
  189. else if (name == "C::f1")
  190. {
  191. span_c_f1_count++;
  192. }
  193. else if (name == "C::f2")
  194. {
  195. span_c_f2_count++;
  196. }
  197. else if (name == "D::library")
  198. {
  199. span_d_lib_count++;
  200. }
  201. else if (name == "D::f1")
  202. {
  203. span_d_f1_count++;
  204. }
  205. else if (name == "D::f2")
  206. {
  207. span_d_f2_count++;
  208. }
  209. else if (name == "E::library")
  210. {
  211. span_e_lib_count++;
  212. }
  213. else if (name == "E::f1")
  214. {
  215. span_e_f1_count++;
  216. }
  217. else if (name == "E::f2")
  218. {
  219. span_e_f2_count++;
  220. }
  221. else if (name == "F::library")
  222. {
  223. span_f_lib_count++;
  224. }
  225. else if (name == "F::f1")
  226. {
  227. span_f_f1_count++;
  228. }
  229. else if (name == "F::f2")
  230. {
  231. span_f_f2_count++;
  232. }
  233. else if (name == "G::library")
  234. {
  235. span_g_lib_count++;
  236. }
  237. else if (name == "G::f1")
  238. {
  239. span_g_f1_count++;
  240. }
  241. else if (name == "G::f2")
  242. {
  243. span_g_f2_count++;
  244. }
  245. else if (name == "H::library")
  246. {
  247. span_h_lib_count++;
  248. }
  249. else if (name == "H::f1")
  250. {
  251. span_h_f1_count++;
  252. }
  253. else if (name == "H::f2")
  254. {
  255. span_h_f2_count++;
  256. }
  257. else
  258. {
  259. unknown_span_count++;
  260. }
  261. return result;
  262. }
  263. #if OPENTELEMETRY_ABI_VERSION_NO == 1
  264. void ForceFlushWithMicroseconds(uint64_t /* timeout */) noexcept override {}
  265. void CloseWithMicroseconds(uint64_t /* timeout */) noexcept override {}
  266. #endif /* OPENTELEMETRY_ABI_VERSION_NO */
  267. };
  268. class MyTracerProvider : public trace::TracerProvider
  269. {
  270. public:
  271. static std::shared_ptr<trace::TracerProvider> Create()
  272. {
  273. std::shared_ptr<trace::TracerProvider> result(new MyTracerProvider());
  274. return result;
  275. }
  276. #if OPENTELEMETRY_ABI_VERSION_NO >= 2
  277. nostd::shared_ptr<trace::Tracer> GetTracer(
  278. nostd::string_view /* name */,
  279. nostd::string_view /* version */,
  280. nostd::string_view /* schema_url */,
  281. const common::KeyValueIterable * /* attributes */) noexcept override
  282. {
  283. nostd::shared_ptr<trace::Tracer> result(new MyTracer());
  284. return result;
  285. }
  286. #else
  287. nostd::shared_ptr<trace::Tracer> GetTracer(nostd::string_view /* name */,
  288. nostd::string_view /* version */,
  289. nostd::string_view /* schema_url */) noexcept override
  290. {
  291. nostd::shared_ptr<trace::Tracer> result(new MyTracer());
  292. return result;
  293. }
  294. #endif
  295. };
  296. void setup_otel()
  297. {
  298. std::shared_ptr<opentelemetry::trace::TracerProvider> provider = MyTracerProvider::Create();
  299. // The whole point of this test is to make sure
  300. // that the API singleton behind SetTracerProvider()
  301. // works for all components, static and dynamic.
  302. // Set the global tracer provider
  303. trace_api::Provider::SetTracerProvider(provider);
  304. }
  305. void cleanup_otel()
  306. {
  307. std::shared_ptr<opentelemetry::trace::TracerProvider> provider(
  308. new opentelemetry::trace::NoopTracerProvider());
  309. // Set the global tracer provider
  310. trace_api::Provider::SetTracerProvider(provider);
  311. }
  312. // TODO: Remove once windows api singletons are supported.
  313. // See https://github.com/open-telemetry/opentelemetry-cpp/issues/2534
  314. #ifdef _WIN32
  315. # define RUN_FAILING_WINDOWS_TEST 0
  316. #else
  317. # define RUN_FAILING_WINDOWS_TEST 1
  318. #endif
  319. TEST(SingletonTest, Uniqueness)
  320. {
  321. do_something();
  322. EXPECT_EQ(span_a_lib_count, 0);
  323. EXPECT_EQ(span_a_f1_count, 0);
  324. EXPECT_EQ(span_a_f2_count, 0);
  325. EXPECT_EQ(span_b_lib_count, 0);
  326. EXPECT_EQ(span_b_f1_count, 0);
  327. EXPECT_EQ(span_b_f2_count, 0);
  328. EXPECT_EQ(span_c_lib_count, 0);
  329. EXPECT_EQ(span_c_f1_count, 0);
  330. EXPECT_EQ(span_c_f2_count, 0);
  331. EXPECT_EQ(span_d_lib_count, 0);
  332. EXPECT_EQ(span_d_f1_count, 0);
  333. EXPECT_EQ(span_d_f2_count, 0);
  334. EXPECT_EQ(span_e_lib_count, 0);
  335. EXPECT_EQ(span_e_f1_count, 0);
  336. EXPECT_EQ(span_e_f2_count, 0);
  337. EXPECT_EQ(span_f_lib_count, 0);
  338. EXPECT_EQ(span_f_f1_count, 0);
  339. EXPECT_EQ(span_f_f2_count, 0);
  340. EXPECT_EQ(span_g_lib_count, 0);
  341. EXPECT_EQ(span_g_f1_count, 0);
  342. EXPECT_EQ(span_g_f2_count, 0);
  343. EXPECT_EQ(span_h_lib_count, 0);
  344. EXPECT_EQ(span_h_f1_count, 0);
  345. EXPECT_EQ(span_h_f2_count, 0);
  346. EXPECT_EQ(unknown_span_count, 0);
  347. reset_counts();
  348. setup_otel();
  349. do_something();
  350. EXPECT_EQ(span_a_lib_count, 1);
  351. EXPECT_EQ(span_a_f1_count, 2);
  352. EXPECT_EQ(span_a_f2_count, 1);
  353. EXPECT_EQ(span_b_lib_count, 1);
  354. EXPECT_EQ(span_b_f1_count, 2);
  355. EXPECT_EQ(span_b_f2_count, 1);
  356. #if RUN_FAILING_WINDOWS_TEST
  357. EXPECT_EQ(span_c_lib_count, 1); // Fails with shared libraries on Windows
  358. EXPECT_EQ(span_c_f1_count, 2); // Fails with shared libraries on Windows
  359. EXPECT_EQ(span_c_f2_count, 1); // Fails with shared libraries on Windows
  360. EXPECT_EQ(span_d_lib_count, 1); // Fails with shared libraries on Windows
  361. EXPECT_EQ(span_d_f1_count, 2); // Fails with shared libraries on Windows
  362. EXPECT_EQ(span_d_f2_count, 1); // Fails with shared libraries on Windows
  363. EXPECT_EQ(span_e_lib_count, 1); // Fails with shared libraries on Windows
  364. EXPECT_EQ(span_e_f1_count, 2); // Fails with shared libraries on Windows
  365. EXPECT_EQ(span_e_f2_count, 1); // Fails with shared libraries on Windows
  366. EXPECT_EQ(span_f_lib_count, 1); // Fails with shared libraries on Windows
  367. EXPECT_EQ(span_f_f1_count, 2); // Fails with shared libraries on Windows
  368. EXPECT_EQ(span_f_f2_count, 1); // Fails with shared libraries on Windows
  369. #endif
  370. #ifndef BAZEL_BUILD
  371. # if RUN_FAILING_WINDOWS_TEST
  372. EXPECT_EQ(span_g_lib_count, 1); // Fails with shared libraries on Windows
  373. EXPECT_EQ(span_g_f1_count, 2); // Fails with shared libraries on Windows
  374. EXPECT_EQ(span_g_f2_count, 1); // Fails with shared libraries on Windows
  375. EXPECT_EQ(span_h_lib_count, 1); // Fails with shared libraries on Windows
  376. EXPECT_EQ(span_h_f1_count, 2); // Fails with shared libraries on Windows
  377. EXPECT_EQ(span_h_f2_count, 1); // Fails with shared libraries on Windows
  378. # endif
  379. #endif
  380. EXPECT_EQ(unknown_span_count, 0);
  381. reset_counts();
  382. cleanup_otel();
  383. do_something();
  384. EXPECT_EQ(span_a_lib_count, 0);
  385. EXPECT_EQ(span_a_f1_count, 0);
  386. EXPECT_EQ(span_a_f2_count, 0);
  387. EXPECT_EQ(span_b_lib_count, 0);
  388. EXPECT_EQ(span_b_f1_count, 0);
  389. EXPECT_EQ(span_b_f2_count, 0);
  390. EXPECT_EQ(span_c_lib_count, 0);
  391. EXPECT_EQ(span_c_f1_count, 0);
  392. EXPECT_EQ(span_c_f2_count, 0);
  393. EXPECT_EQ(span_d_lib_count, 0);
  394. EXPECT_EQ(span_d_f1_count, 0);
  395. EXPECT_EQ(span_d_f2_count, 0);
  396. EXPECT_EQ(span_e_lib_count, 0);
  397. EXPECT_EQ(span_e_f1_count, 0);
  398. EXPECT_EQ(span_e_f2_count, 0);
  399. EXPECT_EQ(span_f_lib_count, 0);
  400. EXPECT_EQ(span_f_f1_count, 0);
  401. EXPECT_EQ(span_f_f2_count, 0);
  402. EXPECT_EQ(span_g_lib_count, 0);
  403. EXPECT_EQ(span_g_f1_count, 0);
  404. EXPECT_EQ(span_g_f2_count, 0);
  405. EXPECT_EQ(span_h_lib_count, 0);
  406. EXPECT_EQ(span_h_f1_count, 0);
  407. EXPECT_EQ(span_h_f2_count, 0);
  408. EXPECT_EQ(unknown_span_count, 0);
  409. }