summaryrefslogtreecommitdiffstats
path: root/src/jaegertracing/opentelemetry-cpp/sdk/test/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/jaegertracing/opentelemetry-cpp/sdk/test/common')
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/BUILD153
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/CMakeLists.txt37
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/atomic_unique_ptr_test.cc42
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/attribute_utils_test.cc53
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/attributemap_hash_benchmark.cc22
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/attributemap_hash_test.cc32
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/baseline_circular_buffer.h88
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_benchmark.cc133
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_range_test.cc59
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_test.cc161
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/empty_attributes_test.cc19
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/fast_random_number_generator_test.cc22
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/global_log_handle_test.cc67
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_benchmark.cc35
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_fork_test.cc53
-rw-r--r--src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_test.cc35
16 files changed, 1011 insertions, 0 deletions
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/BUILD b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/BUILD
new file mode 100644
index 000000000..91d56996f
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/BUILD
@@ -0,0 +1,153 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "random_test",
+ srcs = [
+ "random_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//sdk/src/common:random",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "fast_random_number_generator_test",
+ srcs = [
+ "fast_random_number_generator_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//sdk/src/common:random",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+otel_cc_benchmark(
+ name = "random_benchmark",
+ srcs = ["random_benchmark.cc"],
+ tags = ["test"],
+ deps = ["//sdk/src/common:random"],
+)
+
+cc_test(
+ name = "atomic_unique_ptr_test",
+ srcs = [
+ "atomic_unique_ptr_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//api",
+ "//sdk:headers",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "circular_buffer_range_test",
+ srcs = [
+ "circular_buffer_range_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//api",
+ "//sdk:headers",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "random_fork_test",
+ srcs = [
+ "random_fork_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//sdk/src/common:random",
+ ],
+)
+
+cc_library(
+ name = "baseline_circular_buffer",
+ hdrs = [
+ "baseline_circular_buffer.h",
+ ],
+ include_prefix = "test/common",
+ deps = [
+ "//api",
+ ],
+)
+
+otel_cc_benchmark(
+ name = "circular_buffer_benchmark",
+ srcs = ["circular_buffer_benchmark.cc"],
+ tags = ["test"],
+ deps = [
+ ":baseline_circular_buffer",
+ "//sdk:headers",
+ ],
+)
+
+cc_test(
+ name = "empty_attributes_test",
+ srcs = [
+ "empty_attributes_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//api",
+ "//sdk:headers",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "attribute_utils_test",
+ srcs = [
+ "attribute_utils_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//api",
+ "//sdk:headers",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "global_log_handle_test",
+ srcs = [
+ "global_log_handle_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//api",
+ "//sdk:headers",
+ "//sdk/src/common:global_log_handler",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "attributemap_hash_test",
+ srcs = [
+ "attributemap_hash_test.cc",
+ ],
+ tags = ["test"],
+ deps = [
+ "//api",
+ "//sdk:headers",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+otel_cc_benchmark(
+ name = "attributemap_hash_benchmark",
+ srcs = ["attributemap_hash_benchmark.cc"],
+ tags = ["test"],
+ deps = [
+ "//api",
+ "//sdk:headers",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/CMakeLists.txt
new file mode 100644
index 000000000..0fefc86b1
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/CMakeLists.txt
@@ -0,0 +1,37 @@
+foreach(
+ testname
+ random_test
+ fast_random_number_generator_test
+ atomic_unique_ptr_test
+ circular_buffer_range_test
+ circular_buffer_test
+ attribute_utils_test
+ attributemap_hash_test
+ global_log_handle_test)
+
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(
+ ${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
+ opentelemetry_common opentelemetry_trace)
+
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX trace.
+ TEST_LIST ${testname})
+endforeach()
+
+add_executable(random_fork_test random_fork_test.cc)
+target_link_libraries(random_fork_test opentelemetry_common)
+add_test(random_fork_test random_fork_test)
+
+add_executable(random_benchmark random_benchmark.cc)
+target_link_libraries(random_benchmark benchmark::benchmark
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_common)
+
+add_executable(circular_buffer_benchmark circular_buffer_benchmark.cc)
+target_link_libraries(circular_buffer_benchmark benchmark::benchmark
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+
+add_executable(attributemap_hash_benchmark attributemap_hash_benchmark.cc)
+target_link_libraries(attributemap_hash_benchmark benchmark::benchmark
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_common)
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/atomic_unique_ptr_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/atomic_unique_ptr_test.cc
new file mode 100644
index 000000000..aa6d88a00
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/atomic_unique_ptr_test.cc
@@ -0,0 +1,42 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/sdk/common/atomic_unique_ptr.h"
+
+#include <gtest/gtest.h>
+using opentelemetry::sdk::common::AtomicUniquePtr;
+
+TEST(AtomicUniquePtrTest, SwapIfNullWithNull)
+{
+ AtomicUniquePtr<int> ptr;
+ EXPECT_TRUE(ptr.IsNull());
+
+ std::unique_ptr<int> x{new int{33}};
+ EXPECT_TRUE(ptr.SwapIfNull(x));
+ EXPECT_EQ(x, nullptr);
+}
+
+TEST(AtomicUniquePtrTest, SwapIfNullWithNonNull)
+{
+ AtomicUniquePtr<int> ptr;
+ ptr.Reset(new int{11});
+ std::unique_ptr<int> x{new int{33}};
+ EXPECT_TRUE(!ptr.SwapIfNull(x));
+ EXPECT_NE(x, nullptr);
+ EXPECT_EQ(*x, 33);
+ EXPECT_EQ(*ptr, 11);
+}
+
+TEST(AtomicUniquePtrTest, Swap)
+{
+ AtomicUniquePtr<int> ptr;
+ EXPECT_TRUE(ptr.IsNull());
+
+ ptr.Reset(new int{11});
+ std::unique_ptr<int> x{new int{33}};
+ ptr.Swap(x);
+ EXPECT_FALSE(ptr.IsNull());
+ EXPECT_NE(x, nullptr);
+ EXPECT_EQ(*x, 11);
+ EXPECT_EQ(*ptr, 33);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attribute_utils_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attribute_utils_test.cc
new file mode 100644
index 000000000..b7ef17244
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attribute_utils_test.cc
@@ -0,0 +1,53 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/sdk/common/attribute_utils.h"
+
+#include <gtest/gtest.h>
+
+TEST(AttributeMapTest, DefaultConstruction)
+{
+
+ opentelemetry::sdk::common::AttributeMap attribute_map;
+ EXPECT_EQ(attribute_map.GetAttributes().size(), 0);
+}
+
+TEST(OrderedAttributeMapTest, DefaultConstruction)
+{
+ opentelemetry::sdk::common::OrderedAttributeMap attribute_map;
+ EXPECT_EQ(attribute_map.GetAttributes().size(), 0);
+}
+
+TEST(AttributeMapTest, AttributesConstruction)
+{
+ const int kNumAttributes = 3;
+ std::string keys[kNumAttributes] = {"attr1", "attr2", "attr3"};
+ int values[kNumAttributes] = {15, 24, 37};
+ std::map<std::string, int> attributes = {
+ {keys[0], values[0]}, {keys[1], values[1]}, {keys[2], values[2]}};
+
+ opentelemetry::common::KeyValueIterableView<std::map<std::string, int>> iterable(attributes);
+ opentelemetry::sdk::common::AttributeMap attribute_map(iterable);
+
+ for (int i = 0; i < kNumAttributes; i++)
+ {
+ EXPECT_EQ(opentelemetry::nostd::get<int>(attribute_map.GetAttributes().at(keys[i])), values[i]);
+ }
+}
+
+TEST(OrderedAttributeMapTest, AttributesConstruction)
+{
+ const int kNumAttributes = 3;
+ std::string keys[kNumAttributes] = {"attr1", "attr2", "attr3"};
+ int values[kNumAttributes] = {15, 24, 37};
+ std::map<std::string, int> attributes = {
+ {keys[0], values[0]}, {keys[1], values[1]}, {keys[2], values[2]}};
+
+ opentelemetry::common::KeyValueIterableView<std::map<std::string, int>> iterable(attributes);
+ opentelemetry::sdk::common::OrderedAttributeMap attribute_map(iterable);
+
+ for (int i = 0; i < kNumAttributes; i++)
+ {
+ EXPECT_EQ(opentelemetry::nostd::get<int>(attribute_map.GetAttributes().at(keys[i])), values[i]);
+ }
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attributemap_hash_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attributemap_hash_benchmark.cc
new file mode 100644
index 000000000..811ecb23d
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attributemap_hash_benchmark.cc
@@ -0,0 +1,22 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include <benchmark/benchmark.h>
+#include "opentelemetry/sdk/common/attributemap_hash.h"
+
+using namespace opentelemetry::sdk::common;
+namespace
+{
+void BM_AttributeMapHash(benchmark::State &state)
+{
+ OrderedAttributeMap map1 = {{"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}, {"k4", "v4"},
+ {"k5", true}, {"k6", 12}, {"k7", 12.209}};
+ while (state.KeepRunning())
+ {
+ benchmark::DoNotOptimize(GetHashForAttributeMap(map1));
+ }
+}
+BENCHMARK(BM_AttributeMapHash);
+
+} // namespace
+BENCHMARK_MAIN();
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attributemap_hash_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attributemap_hash_test.cc
new file mode 100644
index 000000000..7d2748670
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/attributemap_hash_test.cc
@@ -0,0 +1,32 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/sdk/common/attributemap_hash.h"
+#include <gtest/gtest.h>
+
+using namespace opentelemetry::sdk::common;
+TEST(AttributeMapHashTest, BasicTests)
+{
+ {
+ OrderedAttributeMap map1 = {{"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}};
+ OrderedAttributeMap map2 = {{"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}, {"k4", "v4"}};
+ OrderedAttributeMap map3 = {{"k3", "v3"}, {"k1", "v1"}, {"k2", "v2"}};
+
+ EXPECT_TRUE(GetHashForAttributeMap(map1) != 0);
+ EXPECT_TRUE(GetHashForAttributeMap(map1) == GetHashForAttributeMap(map1));
+ EXPECT_TRUE(GetHashForAttributeMap(map1) != GetHashForAttributeMap(map2));
+ EXPECT_TRUE(GetHashForAttributeMap(map1) == GetHashForAttributeMap(map3));
+ }
+
+ {
+ OrderedAttributeMap map1 = {{"k1", 10}, {"k2", true}, {"k3", 12.22}};
+ OrderedAttributeMap map2 = {{"k3", 12.22}, {"k1", 10}, {"k2", true}};
+ EXPECT_TRUE(GetHashForAttributeMap(map1) == GetHashForAttributeMap(map2));
+ EXPECT_TRUE(GetHashForAttributeMap(map1) != 0);
+ }
+
+ {
+ OrderedAttributeMap map1 = {};
+ EXPECT_TRUE(GetHashForAttributeMap(map1) == 0);
+ }
+} \ No newline at end of file
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/baseline_circular_buffer.h b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/baseline_circular_buffer.h
new file mode 100644
index 000000000..398a4d038
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/baseline_circular_buffer.h
@@ -0,0 +1,88 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace testing
+{
+/**
+ * A locking circular buffer.
+ *
+ * Used as a baseline in benchmarking.
+ */
+template <class T>
+class BaselineCircularBuffer
+{
+public:
+ explicit BaselineCircularBuffer(size_t max_size) : data_{max_size} {}
+
+ /**
+ * Add an element to the circular buffer.
+ * @param element the element to add
+ * @return true if the element was added successfully
+ */
+ bool Add(std::unique_ptr<T> &element) noexcept { return this->Add(std::move(element)); }
+
+ bool Add(std::unique_ptr<T> &&element) noexcept
+ {
+ std::lock_guard<std::mutex> lock_guard{mutex_};
+ if (tail_ + data_.size() == head_)
+ {
+ return false;
+ }
+ data_[head_ % data_.size()] = std::move(element);
+ head_ += 1;
+ return true;
+ }
+
+ /**
+ * Consume elements in the circular buffer.
+ * @param f the callback to call for each element
+ */
+ template <class F>
+ void Consume(F f) noexcept
+ {
+ std::lock_guard<std::mutex> lock_guard{mutex_};
+ if (head_ == tail_)
+ {
+ return;
+ }
+ auto tail_index = tail_ % data_.size();
+ auto head_index = head_ % data_.size();
+ if (tail_index < head_index)
+ {
+ for (auto i = tail_index; i < head_index; ++i)
+ {
+ f(std::move(data_[i]));
+ }
+ }
+ else
+ {
+ for (auto i = tail_index; i < data_.size(); ++i)
+ {
+ f(std::move(data_[i]));
+ }
+ for (auto i = 0ull; i < head_index; ++i)
+ {
+ f(std::move(data_[i]));
+ }
+ }
+ tail_ = head_;
+ }
+
+private:
+ std::mutex mutex_;
+ uint64_t head_{0};
+ uint64_t tail_{0};
+ std::vector<std::unique_ptr<T>> data_;
+};
+} // namespace testing
+OPENTELEMETRY_END_NAMESPACE
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_benchmark.cc
new file mode 100644
index 000000000..1f2b9b42c
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_benchmark.cc
@@ -0,0 +1,133 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "benchmark/benchmark.h"
+
+#include <atomic>
+#include <cstdint>
+#include <iostream>
+#include <memory>
+#include <random>
+#include <thread>
+#include <vector>
+
+#include "opentelemetry/sdk/common/circular_buffer.h"
+#include "test/common/baseline_circular_buffer.h"
+using opentelemetry::sdk::common::AtomicUniquePtr;
+using opentelemetry::sdk::common::CircularBuffer;
+using opentelemetry::sdk::common::CircularBufferRange;
+using opentelemetry::testing::BaselineCircularBuffer;
+
+const int N = 10000;
+
+static uint64_t ConsumeBufferNumbers(BaselineCircularBuffer<uint64_t> &buffer) noexcept
+{
+ uint64_t result = 0;
+ buffer.Consume([&](std::unique_ptr<uint64_t> &&x) {
+ result += *x;
+ x.reset();
+ });
+ return result;
+}
+
+static uint64_t ConsumeBufferNumbers(CircularBuffer<uint64_t> &buffer) noexcept
+{
+ uint64_t result = 0;
+ buffer.Consume(buffer.size(),
+ [&](CircularBufferRange<AtomicUniquePtr<uint64_t>> &range) noexcept {
+ range.ForEach([&](AtomicUniquePtr<uint64_t> &ptr) noexcept {
+ result += *ptr;
+ ptr.Reset();
+ return true;
+ });
+ });
+ return result;
+}
+
+template <class Buffer>
+static void GenerateNumbersForThread(Buffer &buffer, int n, std::atomic<uint64_t> &sum) noexcept
+{
+ thread_local std::mt19937_64 random_number_generator{std::random_device{}()};
+ for (int i = 0; i < n; ++i)
+ {
+ auto x = random_number_generator();
+ std::unique_ptr<uint64_t> element{new uint64_t{x}};
+ if (buffer.Add(element))
+ {
+ sum += x;
+ }
+ }
+}
+
+template <class Buffer>
+static uint64_t GenerateNumbers(Buffer &buffer, int num_threads, int n) noexcept
+{
+ std::atomic<uint64_t> sum{0};
+ std::vector<std::thread> threads(num_threads);
+ for (auto &thread : threads)
+ {
+ thread = std::thread{GenerateNumbersForThread<Buffer>, std::ref(buffer), n, std::ref(sum)};
+ }
+ for (auto &thread : threads)
+ {
+ thread.join();
+ }
+ return sum;
+}
+
+template <class Buffer>
+static void ConsumeNumbers(Buffer &buffer, uint64_t &sum, std::atomic<bool> &finished) noexcept
+{
+ while (!finished)
+ {
+ sum += ConsumeBufferNumbers(buffer);
+ }
+ sum += ConsumeBufferNumbers(buffer);
+}
+
+template <class Buffer>
+static void RunSimulation(Buffer &buffer, int num_threads, int n) noexcept
+{
+ std::atomic<bool> finished{false};
+ uint64_t consumer_sum{0};
+ std::thread consumer_thread{ConsumeNumbers<Buffer>, std::ref(buffer), std::ref(consumer_sum),
+ std::ref(finished)};
+ uint64_t producer_sum = GenerateNumbers(buffer, num_threads, n);
+ finished = true;
+ consumer_thread.join();
+ if (consumer_sum != producer_sum)
+ {
+ std::cerr << "Sumulation failed: consumer_sum != producer_sum\n";
+ std::terminate();
+ }
+}
+
+static void BM_BaselineBuffer(benchmark::State &state)
+{
+ const size_t max_elements = 500;
+ const int num_threads = static_cast<int>(state.range(0));
+ const int n = static_cast<int>(N / num_threads);
+ BaselineCircularBuffer<uint64_t> buffer{max_elements};
+ for (auto _ : state)
+ {
+ RunSimulation(buffer, num_threads, n);
+ }
+}
+
+BENCHMARK(BM_BaselineBuffer)->Arg(1)->Arg(2)->Arg(4);
+
+static void BM_LockFreeBuffer(benchmark::State &state)
+{
+ const size_t max_elements = 500;
+ const int num_threads = static_cast<int>(state.range(0));
+ const int n = static_cast<int>(N / num_threads);
+ CircularBuffer<uint64_t> buffer{max_elements};
+ for (auto _ : state)
+ {
+ RunSimulation(buffer, num_threads, n);
+ }
+}
+
+BENCHMARK(BM_LockFreeBuffer)->Arg(1)->Arg(2)->Arg(4);
+
+BENCHMARK_MAIN();
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_range_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_range_test.cc
new file mode 100644
index 000000000..585270468
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_range_test.cc
@@ -0,0 +1,59 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/sdk/common/circular_buffer_range.h"
+
+#include <iterator>
+
+#include <gtest/gtest.h>
+using opentelemetry::sdk::common::CircularBufferRange;
+
+TEST(CircularBufferRangeTest, ForEach)
+{
+ int array1[] = {1, 2, 3, 4};
+ int array2[] = {5, 6, 7};
+ CircularBufferRange<int> range{array1, array2};
+
+ int x = 0;
+ range.ForEach([&](int y) {
+ EXPECT_EQ(++x, y);
+ return true;
+ });
+ EXPECT_EQ(x, 7);
+}
+
+TEST(CircularBufferRangeTest, ForEachWithExit)
+{
+ int array1[] = {1, 2, 3, 4};
+ int array2[] = {5, 6, 7};
+ CircularBufferRange<int> range{array1, array2};
+
+ int x = 0;
+ range.ForEach([&](int y) {
+ EXPECT_EQ(++x, y);
+ return false;
+ });
+ EXPECT_EQ(x, 1);
+
+ x = 0;
+ range.ForEach([&](int y) {
+ EXPECT_EQ(++x, y);
+ return y != 5;
+ });
+ EXPECT_EQ(x, 5);
+}
+
+TEST(CircularBufferRangeTest, Conversion)
+{
+ int array1[] = {1, 2, 3, 4};
+ int array2[] = {5, 6, 7};
+ CircularBufferRange<int> range{array1, array2};
+
+ CircularBufferRange<const int> range2{range};
+ int x = 0;
+ range2.ForEach([&](int y) {
+ EXPECT_EQ(++x, y);
+ return true;
+ });
+ EXPECT_EQ(x, 7);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_test.cc
new file mode 100644
index 000000000..a20c3e42a
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_test.cc
@@ -0,0 +1,161 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/sdk/common/circular_buffer.h"
+
+#include <algorithm>
+#include <cassert>
+#include <random>
+#include <thread>
+
+#include <gtest/gtest.h>
+using opentelemetry::sdk::common::AtomicUniquePtr;
+using opentelemetry::sdk::common::CircularBuffer;
+using opentelemetry::sdk::common::CircularBufferRange;
+
+static thread_local std::mt19937 RandomNumberGenerator{std::random_device{}()};
+
+static void GenerateRandomNumbers(CircularBuffer<uint32_t> &buffer,
+ std::vector<uint32_t> &numbers,
+ int n)
+{
+ for (int i = 0; i < n; ++i)
+ {
+ auto value = static_cast<uint32_t>(RandomNumberGenerator());
+ std::unique_ptr<uint32_t> x{new uint32_t{value}};
+ if (buffer.Add(x))
+ {
+ numbers.push_back(value);
+ }
+ }
+}
+
+static void RunNumberProducers(CircularBuffer<uint32_t> &buffer,
+ std::vector<uint32_t> &numbers,
+ int num_threads,
+ int n)
+{
+ std::vector<std::vector<uint32_t>> thread_numbers(num_threads);
+ std::vector<std::thread> threads(num_threads);
+ for (int thread_index = 0; thread_index < num_threads; ++thread_index)
+ {
+ threads[thread_index] = std::thread{GenerateRandomNumbers, std::ref(buffer),
+ std::ref(thread_numbers[thread_index]), n};
+ }
+ for (auto &thread : threads)
+ {
+ thread.join();
+ }
+ for (int thread_index = 0; thread_index < num_threads; ++thread_index)
+ {
+ numbers.insert(numbers.end(), thread_numbers[thread_index].begin(),
+ thread_numbers[thread_index].end());
+ }
+}
+
+void RunNumberConsumer(CircularBuffer<uint32_t> &buffer,
+ std::atomic<bool> &exit,
+ std::vector<uint32_t> &numbers)
+{
+ while (true)
+ {
+ if (exit && buffer.Peek().empty())
+ {
+ return;
+ }
+ auto n = std::uniform_int_distribution<size_t>{0, buffer.Peek().size()}(RandomNumberGenerator);
+ buffer.Consume(n, [&](CircularBufferRange<AtomicUniquePtr<uint32_t>> range) noexcept {
+ assert(range.size() == n);
+ range.ForEach([&](AtomicUniquePtr<uint32_t> &ptr) noexcept {
+ assert(!ptr.IsNull());
+ numbers.push_back(*ptr);
+ ptr.Reset();
+ return true;
+ });
+ });
+ }
+}
+
+TEST(CircularBufferTest, Add)
+{
+ CircularBuffer<int> buffer{10};
+
+ std::unique_ptr<int> x{new int{11}};
+ EXPECT_TRUE(buffer.Add(x));
+ EXPECT_EQ(x, nullptr);
+ auto range = buffer.Peek();
+ EXPECT_EQ(range.size(), 1);
+ range.ForEach([](const AtomicUniquePtr<int> &y) {
+ EXPECT_EQ(*y, 11);
+ return true;
+ });
+}
+
+TEST(CircularBufferTest, Clear)
+{
+ CircularBuffer<int> buffer{10};
+
+ std::unique_ptr<int> x{new int{11}};
+ EXPECT_TRUE(buffer.Add(x));
+ EXPECT_EQ(x, nullptr);
+ buffer.Clear();
+ EXPECT_TRUE(buffer.empty());
+}
+
+TEST(CircularBufferTest, AddOnFull)
+{
+ CircularBuffer<int> buffer{10};
+ for (int i = 0; i < static_cast<int>(buffer.max_size()); ++i)
+ {
+ std::unique_ptr<int> x{new int{i}};
+ EXPECT_TRUE(buffer.Add(x));
+ }
+ std::unique_ptr<int> x{new int{33}};
+ EXPECT_FALSE(buffer.Add(x));
+ EXPECT_NE(x, nullptr);
+ EXPECT_EQ(*x, 33);
+}
+
+TEST(CircularBufferTest, Consume)
+{
+ CircularBuffer<int> buffer{10};
+ for (int i = 0; i < static_cast<int>(buffer.max_size()); ++i)
+ {
+ std::unique_ptr<int> x{new int{i}};
+ EXPECT_TRUE(buffer.Add(x));
+ }
+ int count = 0;
+ buffer.Consume(5, [&](CircularBufferRange<AtomicUniquePtr<int>> range) noexcept {
+ range.ForEach([&](AtomicUniquePtr<int> &ptr) {
+ EXPECT_EQ(*ptr, count++);
+ ptr.Reset();
+ return true;
+ });
+ });
+ EXPECT_EQ(count, 5);
+}
+
+TEST(CircularBufferTest, Simulation)
+{
+ const int num_producer_threads = 4;
+ const int n = 25000;
+ for (size_t max_size : {1, 2, 10, 50, 100, 1000})
+ {
+ CircularBuffer<uint32_t> buffer{max_size};
+ std::vector<uint32_t> producer_numbers;
+ std::vector<uint32_t> consumer_numbers;
+ auto producers = std::thread{RunNumberProducers, std::ref(buffer), std::ref(producer_numbers),
+ num_producer_threads, n};
+ std::atomic<bool> exit{false};
+ auto consumer = std::thread{RunNumberConsumer, std::ref(buffer), std::ref(exit),
+ std::ref(consumer_numbers)};
+ producers.join();
+ exit = true;
+ consumer.join();
+ std::sort(producer_numbers.begin(), producer_numbers.end());
+ std::sort(consumer_numbers.begin(), consumer_numbers.end());
+
+ EXPECT_EQ(producer_numbers.size(), consumer_numbers.size());
+ EXPECT_EQ(producer_numbers, consumer_numbers);
+ }
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/empty_attributes_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/empty_attributes_test.cc
new file mode 100644
index 000000000..f37ea0a5c
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/empty_attributes_test.cc
@@ -0,0 +1,19 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/sdk/common/empty_attributes.h"
+
+#include <gtest/gtest.h>
+
+TEST(EmptyAttributesTest, TestSize)
+{
+ EXPECT_EQ(opentelemetry::sdk::GetEmptyAttributes().size(), 0);
+}
+
+// Test that GetEmptyAttributes() always returns the same KeyValueIterableView
+TEST(EmptyAttributesTest, TestMemory)
+{
+ auto attributes1 = opentelemetry::sdk::GetEmptyAttributes();
+ auto attributes2 = opentelemetry::sdk::GetEmptyAttributes();
+ EXPECT_EQ(memcmp(&attributes1, &attributes2, sizeof(attributes1)), 0);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/fast_random_number_generator_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/fast_random_number_generator_test.cc
new file mode 100644
index 000000000..e9209fdb6
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/fast_random_number_generator_test.cc
@@ -0,0 +1,22 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "src/common/random.h"
+
+#include <random>
+
+#include <gtest/gtest.h>
+
+using opentelemetry::sdk::common::FastRandomNumberGenerator;
+
+TEST(FastRandomNumberGeneratorTest, GenerateUniqueNumbers)
+{
+ std::seed_seq seed_sequence{1, 2, 3};
+ FastRandomNumberGenerator random_number_generator;
+ random_number_generator.seed(seed_sequence);
+ std::set<uint64_t> values;
+ for (int i = 0; i < 1000; ++i)
+ {
+ EXPECT_TRUE(values.insert(random_number_generator()).second);
+ }
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/global_log_handle_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/global_log_handle_test.cc
new file mode 100644
index 000000000..a38bdc872
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/global_log_handle_test.cc
@@ -0,0 +1,67 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/sdk/common/global_log_handler.h"
+
+#include <gtest/gtest.h>
+
+#include <cstring>
+
+class CustomLogHandler : public opentelemetry::sdk::common::internal_log::LogHandler
+{
+public:
+ void Handle(opentelemetry::sdk::common::internal_log::LogLevel level,
+ const char *,
+ int,
+ const char *msg,
+ const opentelemetry::sdk::common::AttributeMap &) noexcept override
+ {
+ if (level == opentelemetry::sdk::common::internal_log::LogLevel::Debug)
+ {
+ EXPECT_EQ(0, strncmp(msg, "Debug message", 13));
+ }
+ else if (level == opentelemetry::sdk::common::internal_log::LogLevel::Error)
+ {
+ EXPECT_EQ(0, strncmp(msg, "Error message", 13));
+ }
+ else if (level == opentelemetry::sdk::common::internal_log::LogLevel::Info)
+ {
+ EXPECT_EQ(0, strncmp(msg, "Info message", 12));
+ }
+ else if (level == opentelemetry::sdk::common::internal_log::LogLevel::Warning)
+ {
+ EXPECT_EQ(0, strncmp(msg, "Warning message", 15));
+ }
+ ++count;
+ }
+
+ size_t count = 0;
+};
+
+TEST(GlobalLogHandleTest, CustomLogHandler)
+{
+ using opentelemetry::sdk::common::internal_log::LogHandler;
+ auto backup_log_handle =
+ opentelemetry::sdk::common::internal_log::GlobalLogHandler::GetLogHandler();
+ auto backup_log_level = opentelemetry::sdk::common::internal_log::GlobalLogHandler::GetLogLevel();
+
+ auto custom_log_handler = opentelemetry::nostd::shared_ptr<LogHandler>(new CustomLogHandler{});
+ opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogHandler(custom_log_handler);
+ auto before_count = static_cast<CustomLogHandler *>(custom_log_handler.get())->count;
+ opentelemetry::sdk::common::AttributeMap attributes = {
+ {"url", "https://opentelemetry.io/"}, {"content-length", 0}, {"content-type", "text/html"}};
+ OTEL_INTERNAL_LOG_ERROR("Error message");
+ OTEL_INTERNAL_LOG_DEBUG("Debug message. Headers:", attributes);
+ EXPECT_EQ(before_count + 1, static_cast<CustomLogHandler *>(custom_log_handler.get())->count);
+
+ opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogLevel(
+ opentelemetry::sdk::common::internal_log::LogLevel::Debug);
+ OTEL_INTERNAL_LOG_ERROR("Error message");
+ OTEL_INTERNAL_LOG_DEBUG("Debug message. Headers:", attributes);
+ OTEL_INTERNAL_LOG_INFO("Info message");
+ OTEL_INTERNAL_LOG_WARN("Warning message");
+ EXPECT_EQ(before_count + 5, static_cast<CustomLogHandler *>(custom_log_handler.get())->count);
+
+ opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogHandler(backup_log_handle);
+ opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogLevel(backup_log_level);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_benchmark.cc
new file mode 100644
index 000000000..df2ebf95e
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_benchmark.cc
@@ -0,0 +1,35 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "src/common/random.h"
+
+#include <cstdint>
+#include <random>
+
+#include <benchmark/benchmark.h>
+
+namespace
+{
+using opentelemetry::sdk::common::Random;
+
+void BM_RandomIdGeneration(benchmark::State &state)
+{
+ while (state.KeepRunning())
+ {
+ benchmark::DoNotOptimize(Random::GenerateRandom64());
+ }
+}
+BENCHMARK(BM_RandomIdGeneration);
+
+void BM_RandomIdStdGeneration(benchmark::State &state)
+{
+ std::mt19937_64 generator{0};
+ while (state.KeepRunning())
+ {
+ benchmark::DoNotOptimize(generator());
+ }
+}
+BENCHMARK(BM_RandomIdStdGeneration);
+
+} // namespace
+BENCHMARK_MAIN();
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_fork_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_fork_test.cc
new file mode 100644
index 000000000..2db8b9fcd
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_fork_test.cc
@@ -0,0 +1,53 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifdef __unix__
+// Verifies that IDs don't clash after forking the process.
+//
+// See https://github.com/opentracing-contrib/nginx-opentracing/issues/52
+# include "src/common/random.h"
+
+# include <sys/mman.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+# include <cstdio>
+# include <cstdlib>
+# include <iostream>
+using opentelemetry::sdk::common::Random;
+
+static uint64_t *child_id;
+
+int main()
+{
+ // Set up shared memory to communicate between parent and child processes.
+ //
+ // See https://stackoverflow.com/a/13274800/4447365
+ child_id = static_cast<uint64_t *>(
+ mmap(nullptr, sizeof(*child_id), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
+ *child_id = 0;
+ if (fork() == 0)
+ {
+ *child_id = Random::GenerateRandom64();
+ exit(EXIT_SUCCESS);
+ }
+ else
+ {
+ wait(nullptr);
+ auto parent_id = Random::GenerateRandom64();
+ auto child_id_copy = *child_id;
+ munmap(static_cast<void *>(child_id), sizeof(*child_id));
+ if (parent_id == child_id_copy)
+ {
+ std::cerr << "Child and parent ids are the same value " << parent_id << "\n";
+ return -1;
+ }
+ }
+ return 0;
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_test.cc b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_test.cc
new file mode 100644
index 000000000..35cfd4a1e
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/sdk/test/common/random_test.cc
@@ -0,0 +1,35 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "src/common/random.h"
+
+#include <algorithm>
+#include <iterator>
+
+#include <gtest/gtest.h>
+using opentelemetry::sdk::common::Random;
+
+TEST(RandomTest, GenerateRandom64)
+{
+ EXPECT_NE(Random::GenerateRandom64(), Random::GenerateRandom64());
+}
+
+TEST(RandomTest, GenerateRandomBuffer)
+{
+ uint8_t buf1[8] = {0};
+ uint8_t buf2[8] = {0};
+ Random::GenerateRandomBuffer(buf1);
+ Random::GenerateRandomBuffer(buf2);
+ EXPECT_FALSE(std::equal(std::begin(buf1), std::end(buf1), std::begin(buf2)));
+
+ // Edge cases.
+ for (auto size : {7, 8, 9, 16, 17})
+ {
+ std::vector<uint8_t> buf1(size);
+ std::vector<uint8_t> buf2(size);
+
+ Random::GenerateRandomBuffer(buf1);
+ Random::GenerateRandomBuffer(buf2);
+ EXPECT_FALSE(std::equal(std::begin(buf1), std::end(buf1), std::begin(buf2)));
+ }
+}