summaryrefslogtreecommitdiffstats
path: root/src/jaegertracing/opentelemetry-cpp/api/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/jaegertracing/opentelemetry-cpp/api/test
parentInitial commit. (diff)
downloadceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz
ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/jaegertracing/opentelemetry-cpp/api/test')
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/CMakeLists.txt15
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/_metrics/BUILD50
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/_metrics/CMakeLists.txt9
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/_metrics/meter_provider_test.cc45
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_instrument_test.cc191
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_metrics_test.cc83
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/baggage/BUILD26
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/baggage/CMakeLists.txt15
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_benchmark.cc117
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_test.cc218
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/BUILD16
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/CMakeLists.txt9
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/baggage_propagator_test.cc113
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/common/BUILD41
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/common/CMakeLists.txt15
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/common/kv_properties_test.cc235
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/common/spinlock_benchmark.cc152
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/common/string_util_test.cc47
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/context/BUILD31
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/context/CMakeLists.txt13
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/context/context_test.cc147
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/BUILD16
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/CMakeLists.txt9
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/composite_propagator_test.cc124
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/context/runtime_context_test.cc135
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/core/BUILD14
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/core/CMakeLists.txt9
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/core/timestamp_test.cc67
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/logs/BUILD33
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/logs/CMakeLists.txt9
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/logs/logger_test.cc165
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/logs/provider_test.cc77
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/metrics/BUILD31
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/metrics/CMakeLists.txt9
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/metrics/meter_provider_test.cc38
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/metrics/noop_sync_instrument_test.cc50
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/BUILD104
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/CMakeLists.txt19
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/function_ref_test.cc36
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/shared_ptr_test.cc189
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/span_test.cc191
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/string_view_test.cc125
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/unique_ptr_test.cc169
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/utility_test.cc56
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/nostd/variant_test.cc119
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/plugin/BUILD17
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/plugin/CMakeLists.txt10
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/plugin/dynamic_load_test.cc14
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/BUILD199
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/CMakeLists.txt29
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/default_span_test.cc24
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/key_value_iterable_view_test.cc68
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/noop_test.cc81
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/BUILD52
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/CMakeLists.txt10
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/b3_propagation_test.cc189
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/http_text_format_test.cc211
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/jaeger_propagation_test.cc168
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/util.h14
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/provider_test.cc36
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/scope_test.cc51
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/span_benchmark.cc129
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/span_context_test.cc55
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_benchmark.cc55
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_test.cc58
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_flags_test.cc43
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_id_test.cc58
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_state_test.cc196
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/test/trace/tracer_test.cc39
69 files changed, 5188 insertions, 0 deletions
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/CMakeLists.txt
new file mode 100644
index 000000000..41125005e
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_subdirectory(core)
+add_subdirectory(context)
+add_subdirectory(plugin)
+add_subdirectory(nostd)
+add_subdirectory(trace)
+if(WITH_METRICS_PREVIEW)
+ add_subdirectory(_metrics)
+else()
+ add_subdirectory(metrics)
+endif()
+if(WITH_LOGS_PREVIEW)
+ add_subdirectory(logs)
+endif()
+add_subdirectory(common)
+add_subdirectory(baggage)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/BUILD
new file mode 100644
index 000000000..6e5b9009b
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/BUILD
@@ -0,0 +1,50 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "meter_provider_test",
+ srcs = [
+ "meter_provider_test.cc",
+ ],
+ tags = [
+ "api",
+ "metrics",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "noop_metrics_test",
+ srcs = [
+ "noop_metrics_test.cc",
+ ],
+ tags = [
+ "api",
+ "metrics",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "noop_instrument_test",
+ srcs = [
+ "noop_instrument_test.cc",
+ ],
+ linkstatic = 1,
+ tags = [
+ "api",
+ "metrics",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/CMakeLists.txt
new file mode 100644
index 000000000..9d70c376e
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/CMakeLists.txt
@@ -0,0 +1,9 @@
+foreach(testname noop_instrument_test meter_provider_test noop_metrics_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX metrics.
+ TEST_LIST ${testname})
+endforeach()
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/meter_provider_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/meter_provider_test.cc
new file mode 100644
index 000000000..507081067
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/meter_provider_test.cc
@@ -0,0 +1,45 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifdef ENABLE_METRICS_PREVIEW
+# include <gtest/gtest.h>
+# include "opentelemetry/_metrics/provider.h"
+# include "opentelemetry/nostd/shared_ptr.h"
+
+using opentelemetry::metrics::Meter;
+using opentelemetry::metrics::MeterProvider;
+using opentelemetry::metrics::Provider;
+namespace nostd = opentelemetry::nostd;
+
+class TestProvider : public MeterProvider
+{
+ nostd::shared_ptr<Meter> GetMeter(nostd::string_view library_name,
+ nostd::string_view library_version) override
+ {
+ return nostd::shared_ptr<Meter>(nullptr);
+ }
+};
+
+TEST(Provider, GetMeterProviderDefault)
+{
+ auto tf = Provider::GetMeterProvider();
+ EXPECT_NE(nullptr, tf);
+}
+
+TEST(Provider, SetMeterProvider)
+{
+ auto tf = nostd::shared_ptr<MeterProvider>(new TestProvider());
+ Provider::SetMeterProvider(tf);
+ ASSERT_EQ(tf, Provider::GetMeterProvider());
+}
+
+TEST(Provider, MultipleMeterProviders)
+{
+ auto tf = nostd::shared_ptr<MeterProvider>(new TestProvider());
+ Provider::SetMeterProvider(tf);
+ auto tf2 = nostd::shared_ptr<MeterProvider>(new TestProvider());
+ Provider::SetMeterProvider(tf2);
+
+ ASSERT_NE(Provider::GetMeterProvider(), tf);
+}
+#endif
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_instrument_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_instrument_test.cc
new file mode 100644
index 000000000..83d8d3960
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_instrument_test.cc
@@ -0,0 +1,191 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifdef ENABLE_METRICS_PREVIEW
+# include <gtest/gtest.h>
+# include <cstring>
+# include <map>
+# include <string>
+
+# include "opentelemetry/_metrics/noop.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace metrics
+{
+
+void noopIntCallback(ObserverResult<int> result)
+{
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+ result.observe(1, labelkv);
+ result.observe(-1, labelkv);
+}
+
+void noopDoubleCallback(ObserverResult<double> result)
+{
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+ result.observe(1.5, labelkv);
+ result.observe(-1.5, labelkv);
+}
+
+TEST(ValueObserver, Observe)
+{
+ NoopValueObserver<int> alpha("test", "none", "unitless", true, &noopIntCallback);
+
+ NoopValueObserver<double> beta("test", "none", "unitless", true, &noopDoubleCallback);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.observe(1, labelkv);
+ beta.observe(1.5, labelkv);
+}
+
+TEST(SumObserver, DefaultConstruction)
+{
+ NoopSumObserver<int> alpha("test", "none", "unitless", true, &noopIntCallback);
+
+ NoopSumObserver<double> beta("test", "none", "unitless", true, &noopDoubleCallback);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.observe(1, labelkv);
+ beta.observe(1.5, labelkv);
+}
+
+TEST(UpDownSumObserver, DefaultConstruction)
+{
+ NoopUpDownSumObserver<int> alpha("test", "none", "unitless", true, &noopIntCallback);
+
+ NoopUpDownSumObserver<double> beta("test", "none", "unitless", true, &noopDoubleCallback);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.observe(1, labelkv);
+ beta.observe(1.0, labelkv);
+ alpha.observe(-1, labelkv);
+ beta.observe(-1.0, labelkv);
+}
+
+TEST(Counter, DefaultConstruction)
+{
+ NoopCounter<int> alpha("test", "none", "unitless", true);
+ NoopCounter<double> beta("other", "none", "unitless", true);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.bind(labelkv);
+
+ auto gamma = alpha.bindNoopCounter(labelkv);
+ auto delta = beta.bindNoopCounter(labelkv);
+
+ gamma->unbind();
+ delta->unbind();
+}
+
+TEST(Counter, Add)
+{
+ NoopCounter<int> alpha("test", "none", "unitless", true);
+ NoopCounter<double> beta("other", "none", "unitless", true);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.add(1, labelkv);
+ beta.add(1.5, labelkv);
+
+ auto gamma = alpha.bindNoopCounter(labelkv);
+ auto delta = beta.bindNoopCounter(labelkv);
+
+ gamma->add(1);
+ delta->add(1.5);
+
+ gamma->unbind();
+ delta->unbind();
+}
+
+TEST(UpDownCounter, DefaultConstruction)
+{
+ NoopUpDownCounter<int> alpha("test", "none", "unitless", true);
+ NoopUpDownCounter<double> beta("other", "none", "unitless", true);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.bind(labelkv);
+
+ auto gamma = alpha.bindNoopUpDownCounter(labelkv);
+ auto delta = beta.bindNoopUpDownCounter(labelkv);
+
+ gamma->unbind();
+ delta->unbind();
+}
+
+TEST(UpDownCounter, Add)
+{
+ NoopUpDownCounter<int> alpha("test", "none", "unitless", true);
+ NoopUpDownCounter<double> beta("other", "none", "unitless", true);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.add(1, labelkv);
+ beta.add(1.5, labelkv);
+
+ auto gamma = alpha.bindNoopUpDownCounter(labelkv);
+ auto delta = beta.bindNoopUpDownCounter(labelkv);
+
+ gamma->add(1);
+ delta->add(1.0);
+ gamma->add(-1);
+ delta->add(-1.0);
+
+ gamma->unbind();
+ delta->unbind();
+}
+
+TEST(ValueRecorder, DefaultConstruction)
+{
+ NoopValueRecorder<int> alpha("test", "none", "unitless", true);
+ NoopValueRecorder<double> beta("other", "none", "unitless", true);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.bind(labelkv);
+
+ auto gamma = alpha.bindNoopValueRecorder(labelkv);
+ auto delta = beta.bindNoopValueRecorder(labelkv);
+
+ gamma->unbind();
+ delta->unbind();
+}
+
+TEST(ValueRecorder, Record)
+{
+ NoopValueRecorder<int> alpha("test", "none", "unitless", true);
+ NoopValueRecorder<double> beta("other", "none", "unitless", true);
+
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+
+ alpha.record(1, labelkv);
+ beta.record(1.5, labelkv);
+
+ auto gamma = alpha.bindNoopValueRecorder(labelkv);
+ auto delta = beta.bindNoopValueRecorder(labelkv);
+
+ gamma->record(1);
+ delta->record(1.5);
+
+ gamma->unbind();
+ delta->unbind();
+}
+
+} // namespace metrics
+OPENTELEMETRY_END_NAMESPACE
+#endif
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_metrics_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_metrics_test.cc
new file mode 100644
index 000000000..cc9d1f4b7
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_metrics_test.cc
@@ -0,0 +1,83 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifdef ENABLE_METRICS_PREVIEW
+# include <gtest/gtest.h>
+# include "opentelemetry/_metrics/instrument.h"
+# include "opentelemetry/_metrics/noop.h"
+# include "opentelemetry/_metrics/observer_result.h"
+# include "opentelemetry/_metrics/sync_instruments.h"
+
+# include <array>
+# include <memory>
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+
+using opentelemetry::metrics::Meter;
+using opentelemetry::metrics::NoopMeter;
+
+void Callback(opentelemetry::metrics::ObserverResult<int> result)
+{
+ std::map<std::string, std::string> labels = {{"key", "value"}};
+ auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels};
+ result.observe(1, labelkv);
+}
+
+TEST(NoopTest, CreateInstruments)
+{
+ auto m = std::unique_ptr<Meter>(new NoopMeter{});
+
+ // Test instrument constructors
+ m->NewIntCounter("Test counter", "For testing", "Unitless", true);
+ m->NewIntUpDownCounter("Test ud counter", "For testing", "Unitless", true);
+ m->NewIntValueRecorder("Test recorder", "For testing", "Unitless", true);
+
+ m->NewIntSumObserver("Test sum obs", "For testing", "Unitless", true, &Callback);
+ m->NewIntUpDownSumObserver("Test udsum obs", "For testing", "Unitless", true, &Callback);
+ m->NewIntValueObserver("Test val obs", "For testing", "Unitless", true, &Callback);
+}
+
+TEST(NoopMeter, RecordBatch)
+{
+ // Test BatchRecord with all supported types
+ // Create Counter and call RecordBatch for all four supported types: short, int, float, and double
+
+ std::unique_ptr<Meter> m{std::unique_ptr<Meter>(new NoopMeter{})};
+
+ std::map<std::string, std::string> labels = {{"Key", "Value"}};
+ auto labelkv = opentelemetry::common::KeyValueIterableView<decltype(labels)>{labels};
+
+ auto s = m->NewShortCounter("Test short counter", "For testing", "Unitless", true);
+
+ std::array<metrics::SynchronousInstrument<short> *, 1> siarr{s.get()};
+ std::array<short, 1> svarr{1};
+ nostd::span<metrics::SynchronousInstrument<short> *> ssp{siarr};
+ nostd::span<short> sval{svarr};
+ m->RecordShortBatch(labelkv, ssp, sval);
+
+ auto i = m->NewIntCounter("Test int counter", "For testing", "Unitless", true);
+
+ std::array<metrics::SynchronousInstrument<int> *, 1> iiarr{i.get()};
+ std::array<int, 1> ivarr{1};
+ nostd::span<metrics::SynchronousInstrument<int> *> isp{iiarr};
+ nostd::span<int> ival{ivarr};
+ m->RecordIntBatch(labelkv, isp, ival);
+
+ auto f = m->NewFloatCounter("Test int counter", "For testing", "Unitless", true);
+
+ std::array<metrics::SynchronousInstrument<float> *, 1> fiarr{f.get()};
+ std::array<float, 1> fvarr{1.0f};
+ nostd::span<metrics::SynchronousInstrument<float> *> fsp{fiarr};
+ nostd::span<float> fval{fvarr};
+ m->RecordFloatBatch(labelkv, fsp, fval);
+
+ auto d = m->NewDoubleCounter("Test int counter", "For testing", "Unitless", true);
+
+ std::array<metrics::SynchronousInstrument<double> *, 1> diarr{d.get()};
+ std::array<double, 1> dvarr{1.0f};
+ nostd::span<metrics::SynchronousInstrument<double> *> dsp{diarr};
+ nostd::span<double> dval{dvarr};
+ m->RecordDoubleBatch(labelkv, dsp, dval);
+}
+OPENTELEMETRY_END_NAMESPACE
+#endif
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/BUILD
new file mode 100644
index 000000000..7c021f46e
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/BUILD
@@ -0,0 +1,26 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "baggage_test",
+ srcs = [
+ "baggage_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+otel_cc_benchmark(
+ name = "baggage_benchmark",
+ srcs = ["baggage_benchmark.cc"],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = ["//api"],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/CMakeLists.txt
new file mode 100644
index 000000000..0d6cba5a0
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/CMakeLists.txt
@@ -0,0 +1,15 @@
+include(GoogleTest)
+
+foreach(testname baggage_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX baggage.
+ TEST_LIST ${testname})
+endforeach()
+add_executable(baggage_benchmark baggage_benchmark.cc)
+target_link_libraries(baggage_benchmark benchmark::benchmark
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+add_subdirectory(propagation)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_benchmark.cc
new file mode 100644
index 000000000..9b7529795
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_benchmark.cc
@@ -0,0 +1,117 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/baggage/baggage.h"
+#include "opentelemetry/nostd/string_view.h"
+
+#include <benchmark/benchmark.h>
+#include <cstdint>
+
+using namespace opentelemetry::baggage;
+namespace nostd = opentelemetry::nostd;
+
+namespace
+{
+
+const size_t kNumEntries = 10;
+
+std::string header_with_custom_entries(size_t num_entries)
+{
+ std::string header;
+ for (size_t i = 0; i < num_entries; i++)
+ {
+ std::string key = "ADecentlyLargekey" + std::to_string(i);
+ std::string value = "ADecentlyLargeValue" + std::to_string(i);
+ header += key + "=" + value;
+ if (i != num_entries - 1)
+ {
+ header += ",";
+ }
+ }
+ return header;
+}
+
+void BM_CreateBaggageFromTenEntries(benchmark::State &state)
+{
+ std::string header = header_with_custom_entries(kNumEntries);
+ while (state.KeepRunning())
+ {
+ auto baggage = Baggage::FromHeader(header);
+ }
+}
+BENCHMARK(BM_CreateBaggageFromTenEntries);
+
+void BM_ExtractBaggageHavingTenEntries(benchmark::State &state)
+{
+ auto baggage = Baggage::FromHeader(header_with_custom_entries(kNumEntries));
+ while (state.KeepRunning())
+ {
+ baggage->GetAllEntries([](nostd::string_view key, nostd::string_view value) { return true; });
+ }
+}
+BENCHMARK(BM_ExtractBaggageHavingTenEntries);
+
+void BM_CreateBaggageFrom180Entries(benchmark::State &state)
+{
+ std::string header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
+ while (state.KeepRunning())
+ {
+ auto baggage = Baggage::FromHeader(header);
+ }
+}
+BENCHMARK(BM_CreateBaggageFrom180Entries);
+
+void BM_ExtractBaggageWith180Entries(benchmark::State &state)
+{
+ auto baggage = Baggage::FromHeader(header_with_custom_entries(Baggage::kMaxKeyValuePairs));
+ while (state.KeepRunning())
+ {
+ baggage->GetAllEntries([](nostd::string_view key, nostd::string_view value) { return true; });
+ }
+}
+BENCHMARK(BM_ExtractBaggageWith180Entries);
+
+void BM_SetValueBaggageWithTenEntries(benchmark::State &state)
+{
+ auto baggage = Baggage::FromHeader(
+ header_with_custom_entries(kNumEntries - 1)); // 9 entries, and add one new
+ while (state.KeepRunning())
+ {
+ auto new_baggage = baggage->Set("new_key", "new_value");
+ }
+}
+BENCHMARK(BM_SetValueBaggageWithTenEntries);
+
+void BM_SetValueBaggageWith180Entries(benchmark::State &state)
+{
+ auto baggage = Baggage::FromHeader(header_with_custom_entries(
+ Baggage::kMaxKeyValuePairs - 1)); // keep 179 entries, and add one new
+ while (state.KeepRunning())
+ {
+ auto new_baggage = baggage->Set("new_key", "new_value");
+ }
+}
+BENCHMARK(BM_SetValueBaggageWith180Entries);
+
+void BM_BaggageToHeaderTenEntries(benchmark::State &state)
+{
+ auto baggage = Baggage::FromHeader(header_with_custom_entries(kNumEntries));
+ while (state.KeepRunning())
+ {
+ auto new_baggage = baggage->ToHeader();
+ }
+}
+BENCHMARK(BM_BaggageToHeaderTenEntries);
+
+void BM_BaggageToHeader180Entries(benchmark::State &state)
+{
+ auto baggage = Baggage::FromHeader(header_with_custom_entries(Baggage::kMaxKeyValuePairs));
+ while (state.KeepRunning())
+ {
+ auto new_baggage = baggage->ToHeader();
+ }
+}
+BENCHMARK(BM_BaggageToHeader180Entries);
+} // namespace
+
+BENCHMARK_MAIN();
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_test.cc
new file mode 100644
index 000000000..9c14fc892
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_test.cc
@@ -0,0 +1,218 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/string_view.h"
+
+#include <gtest/gtest.h>
+#include <string>
+#include <vector>
+
+#include "opentelemetry/baggage/baggage.h"
+
+using namespace opentelemetry;
+using namespace opentelemetry::baggage;
+
+std::string header_with_custom_entries(size_t num_entries)
+{
+ std::string header;
+ for (size_t i = 0; i < num_entries; i++)
+ {
+ std::string key = "key" + std::to_string(i);
+ std::string value = "value" + std::to_string(i);
+ header += key + "=" + value;
+ if (i != num_entries - 1)
+ {
+ header += ",";
+ }
+ }
+ return header;
+}
+
+std::string header_with_custom_size(size_t key_value_size, size_t num_entries)
+{
+ std::string header = "";
+ for (size_t i = 0; i < num_entries; i++)
+ {
+ std::string str = std::to_string(i + 1);
+ str += "=";
+ assert(key_value_size > str.size());
+ for (size_t j = str.size(); j < key_value_size; j++)
+ {
+ str += "a";
+ }
+
+ header += str + ',';
+ }
+
+ header.pop_back();
+ return header;
+}
+
+TEST(BaggageTest, ValidateExtractHeader)
+{
+ auto invalid_key_value_size_header = header_with_custom_size(Baggage::kMaxKeyValueSize + 5, 1);
+
+ struct
+ {
+ const char *input;
+ std::vector<const char *> keys;
+ std::vector<const char *> values;
+ } testcases[] = {
+ {"k1=v1", {"k1"}, {"v1"}},
+ {"k1=V1,K2=v2;metadata,k3=v3",
+ {"k1", "K2", "k3"},
+ {"V1", "v2;metadata", "v3"}}, // metadata is part of value
+ {",k1 =v1,k2=v2 ; metadata,",
+ {"k1", "k2"},
+ {"v1", "v2; metadata"}}, // key and value are trimmed
+ {"1a-2f%40foo=bar%251,a%2A%2Ffoo-_%2Fbar=bar+4",
+ {"1a-2f@foo", "a*/foo-_/bar"},
+ {"bar%1", "bar 4"}}, // decoding is done properly
+ {"k1=v1,invalidmember,k2=v2", {"k1", "k2"}, {"v1", "v2"}}, // invalid member is skipped
+ {",", {}, {}},
+ {",=,", {}, {}},
+ {"", {}, {}},
+ {"k1=%5zv", {}, {}}, // invalid hex : invalid second digit
+ {"k1=%5", {}, {}}, // invalid hex : missing two digits
+ {"k%z2=v1", {}, {}}, // invalid hex : invalid first digit
+ {"k%00=v1", {}, {}}, // key not valid
+ {"k=v%7f", {}, {}}, // value not valid
+ {invalid_key_value_size_header.data(), {}, {}}};
+ for (auto &testcase : testcases)
+ {
+ auto baggage = Baggage::FromHeader(testcase.input);
+ size_t index = 0;
+ baggage->GetAllEntries([&testcase, &index](nostd::string_view key, nostd::string_view value) {
+ EXPECT_EQ(key, testcase.keys[index]);
+ EXPECT_EQ(value, testcase.values[index]);
+ index++;
+ return true;
+ });
+ }
+
+ // For header with maximum threshold pairs, no pair is dropped
+ auto max_pairs_header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
+ EXPECT_EQ(Baggage::FromHeader(max_pairs_header.data())->ToHeader(), max_pairs_header.data());
+
+ // Entries beyond threshold are dropped
+ auto baggage = Baggage::FromHeader(header_with_custom_entries(Baggage::kMaxKeyValuePairs + 1));
+ auto header = baggage->ToHeader();
+ common::KeyValueStringTokenizer kv_str_tokenizer(header);
+ int expected_tokens = Baggage::kMaxKeyValuePairs;
+ EXPECT_EQ(kv_str_tokenizer.NumTokens(), expected_tokens);
+
+ // For header with total size more than threshold, baggage is empty
+ int num_pairs_with_max_size = Baggage::kMaxSize / Baggage::kMaxKeyValueSize;
+ auto invalid_total_size_header =
+ header_with_custom_size(Baggage::kMaxKeyValueSize, num_pairs_with_max_size + 1);
+ EXPECT_EQ(Baggage::FromHeader(invalid_total_size_header.data())->ToHeader(), "");
+}
+
+TEST(BaggageTest, ValidateInjectHeader)
+{
+ struct
+ {
+ std::vector<const char *> keys;
+ std::vector<const char *> values;
+ const char *header;
+ } testcases[] = {{{"k1"}, {"v1"}, "k1=v1"},
+ {{"k3", "k2", "k1"}, {"", "v2", "v1"}, "k1=v1,k2=v2,k3="}, // empty value
+ {{"1a-2f@foo", "a*/foo-_/bar"},
+ {"bar%1", "bar 4"},
+ "a%2A%2Ffoo-_%2Fbar=bar+4,1a-2f%40foo=bar%251"}, // encoding is done properly
+ {{"foo 1"},
+ {"bar 1; metadata ; ;;"},
+ "foo+1=bar+1; metadata ; ;;"}}; // metadata is added without encoding
+
+ for (auto &testcase : testcases)
+ {
+ nostd::shared_ptr<Baggage> baggage(new Baggage{});
+ for (size_t i = 0; i < testcase.keys.size(); i++)
+ {
+ baggage = baggage->Set(testcase.keys[i], testcase.values[i]);
+ }
+ EXPECT_EQ(baggage->ToHeader(), testcase.header);
+ }
+}
+
+TEST(BaggageTest, BaggageGet)
+{
+ auto header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
+ auto baggage = Baggage::FromHeader(header);
+
+ std::string value;
+ EXPECT_TRUE(baggage->GetValue("key0", value));
+ EXPECT_EQ(value, "value0");
+ EXPECT_TRUE(baggage->GetValue("key16", value));
+ EXPECT_EQ(value, "value16");
+
+ EXPECT_TRUE(baggage->GetValue("key31", value));
+ EXPECT_EQ(value, "value31");
+
+ EXPECT_FALSE(baggage->GetValue("key181", value));
+}
+
+TEST(BaggageTest, BaggageSet)
+{
+ std::string header = "k1=v1,k2=v2";
+ auto baggage = Baggage::FromHeader(header);
+
+ std::string value;
+ baggage = baggage->Set("k3", "v3");
+ EXPECT_TRUE(baggage->GetValue("k3", value));
+ EXPECT_EQ(value, "v3");
+
+ baggage = baggage->Set("k3", "v3_1"); // key should be updated with the latest value
+ EXPECT_TRUE(baggage->GetValue("k3", value));
+ EXPECT_EQ(value, "v3_1");
+
+ header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
+ baggage = Baggage::FromHeader(header);
+ baggage = baggage->Set("key0", "0"); // updating on max list should work
+ EXPECT_TRUE(baggage->GetValue("key0", value));
+ EXPECT_EQ(value, "0");
+
+ header = "k1=v1,k2=v2";
+ baggage = Baggage::FromHeader(header);
+ baggage = baggage->Set("", "n_v1"); // adding invalid key, should return copy of same baggage
+ EXPECT_EQ(baggage->ToHeader(), header);
+
+ header = "k1=v1,k2=v2";
+ baggage = Baggage::FromHeader(header);
+ baggage = baggage->Set("k1", "\x1A"); // adding invalid value, should return copy of same baggage
+ EXPECT_EQ(baggage->ToHeader(), header);
+}
+
+TEST(BaggageTest, BaggageRemove)
+{
+ auto header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
+ auto baggage = Baggage::FromHeader(header);
+ std::string value;
+
+ // existing key is removed
+ EXPECT_TRUE(baggage->GetValue("key0", value));
+ auto new_baggage = baggage->Delete("key0");
+ EXPECT_FALSE(new_baggage->GetValue("key0", value));
+
+ // trying Delete on non existent key
+ EXPECT_FALSE(baggage->GetValue("key181", value));
+ auto new_baggage_2 = baggage->Delete("key181");
+ EXPECT_FALSE(new_baggage_2->GetValue("key181", value));
+}
+
+TEST(BaggageTest, BaggageGetAll)
+{
+ std::string baggage_header = "k1=v1,k2=v2,k3=v3";
+ auto baggage = Baggage::FromHeader(baggage_header);
+ const int kNumPairs = 3;
+ nostd::string_view keys[kNumPairs] = {"k1", "k2", "k3"};
+ nostd::string_view values[kNumPairs] = {"v1", "v2", "v3"};
+ size_t index = 0;
+ baggage->GetAllEntries(
+ [&keys, &values, &index](nostd::string_view key, nostd::string_view value) {
+ EXPECT_EQ(key, keys[index]);
+ EXPECT_EQ(value, values[index]);
+ index++;
+ return true;
+ });
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/BUILD
new file mode 100644
index 000000000..1cd4371c1
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/BUILD
@@ -0,0 +1,16 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "baggage_propagator_test",
+ srcs = [
+ "baggage_propagator_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/CMakeLists.txt
new file mode 100644
index 000000000..3b7bd3d07
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/CMakeLists.txt
@@ -0,0 +1,9 @@
+foreach(testname baggage_propagator_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX baggage.
+ TEST_LIST ${testname})
+endforeach()
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/baggage_propagator_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/baggage_propagator_test.cc
new file mode 100644
index 000000000..94fe8b005
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/baggage_propagator_test.cc
@@ -0,0 +1,113 @@
+
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/baggage/propagation/baggage_propagator.h"
+#include <gtest/gtest.h>
+#include <map>
+#include <string>
+#include "opentelemetry/baggage/baggage_context.h"
+
+using namespace opentelemetry;
+using namespace opentelemetry::baggage::propagation;
+
+class BaggageCarrierTest : public context::propagation::TextMapCarrier
+{
+public:
+ BaggageCarrierTest() = default;
+ virtual nostd::string_view Get(nostd::string_view key) const noexcept override
+ {
+ auto it = headers_.find(std::string(key));
+ if (it != headers_.end())
+ {
+ return nostd::string_view(it->second);
+ }
+ return "";
+ }
+ virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
+ {
+ headers_[std::string(key)] = std::string(value);
+ }
+
+ std::map<std::string, std::string> headers_;
+};
+
+static BaggagePropagator format;
+
+TEST(BaggagePropagatorTest, ExtractNoBaggageHeader)
+{
+ BaggageCarrierTest carrier;
+ carrier.headers_ = {};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+ auto ctx2_baggage = baggage::GetBaggage(ctx2);
+ EXPECT_EQ(ctx2_baggage->ToHeader(), "");
+}
+
+TEST(BaggagePropagatorTest, ExtractAndInjectBaggage)
+{
+ // create header string for baggage larger than allowed size (kMaxKeyValueSize)
+ std::string very_large_baggage_header =
+ std::string(baggage::Baggage::kMaxKeyValueSize / 2 + 1, 'k') + "=" +
+ std::string(baggage::Baggage::kMaxKeyValueSize / 2 + 1, 'v');
+
+ std::map<std::string, std::string> baggages = {
+ {"key1=val1,key2=val2", "key1=val1,key2=val2"}, // valid header
+ {"key1 = val1, key2 =val2 ", "key1=val1,key2=val2"}, // valid header with spaces
+ {"key1=val1,key2=val2;prop=1", "key1=val1,key2=val2;prop=1"}, // valid header with properties
+ {"key%2C1=val1,key2=val2%2Cval3",
+ "key%2C1=val1,key2=val2%2Cval3"}, // valid header with url escape
+ {"key1=val1,key2=val2,a,val3", "key1=val1,key2=val2"}, // valid header with invalid value
+ {"key1=,key2=val2", "key1=,key2=val2"}, // valid header with empty value
+ {"invalid_header", ""}, // invalid header
+ {very_large_baggage_header, ""}}; // baggage header larger than allowed size.
+
+ for (auto baggage : baggages)
+ {
+ BaggageCarrierTest carrier1;
+ carrier1.headers_[baggage::kBaggageHeader.data()] = baggage.first;
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier1, ctx1);
+
+ BaggageCarrierTest carrier2;
+ format.Inject(carrier2, ctx2);
+ EXPECT_EQ(carrier2.headers_[baggage::kBaggageHeader.data()], baggage.second);
+
+ std::vector<std::string> fields;
+ format.Fields([&fields](nostd::string_view field) {
+ fields.push_back(field.data());
+ return true;
+ });
+ EXPECT_EQ(fields.size(), 1);
+ EXPECT_EQ(fields[0], baggage::kBaggageHeader.data());
+ }
+}
+
+TEST(BaggagePropagatorTest, InjectEmptyHeader)
+{
+ // Test Missing baggage from context
+ BaggageCarrierTest carrier;
+ context::Context ctx = context::Context{};
+ format.Inject(carrier, ctx);
+ EXPECT_EQ(carrier.headers_.find(baggage::kBaggageHeader), carrier.headers_.end());
+
+ {
+ // Test empty baggage in context
+ BaggageCarrierTest carrier1;
+ carrier1.headers_[baggage::kBaggageHeader.data()] = "";
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier1, ctx1);
+ format.Inject(carrier, ctx2);
+ EXPECT_EQ(carrier.headers_.find(baggage::kBaggageHeader), carrier.headers_.end());
+ }
+ {
+ // Invalid baggage in context
+ BaggageCarrierTest carrier1;
+ carrier1.headers_[baggage::kBaggageHeader.data()] = "InvalidBaggageData";
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier1, ctx1);
+
+ format.Inject(carrier, ctx2);
+ EXPECT_EQ(carrier.headers_.find(baggage::kBaggageHeader), carrier.headers_.end());
+ }
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/common/BUILD
new file mode 100644
index 000000000..5bfc1115d
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/BUILD
@@ -0,0 +1,41 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+otel_cc_benchmark(
+ name = "spinlock_benchmark",
+ srcs = ["spinlock_benchmark.cc"],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = ["//api"],
+)
+
+cc_test(
+ name = "kv_properties_test",
+ srcs = [
+ "kv_properties_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "string_util_test",
+ srcs = [
+ "string_util_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/common/CMakeLists.txt
new file mode 100644
index 000000000..5816b64b1
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/CMakeLists.txt
@@ -0,0 +1,15 @@
+include(GoogleTest)
+
+foreach(testname kv_properties_test string_util_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX common.
+ TEST_LIST ${testname})
+endforeach()
+
+add_executable(spinlock_benchmark spinlock_benchmark.cc)
+target_link_libraries(spinlock_benchmark benchmark::benchmark
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/kv_properties_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/common/kv_properties_test.cc
new file mode 100644
index 000000000..e5d9a2439
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/kv_properties_test.cc
@@ -0,0 +1,235 @@
+
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include <gtest/gtest.h>
+#include <opentelemetry/common/kv_properties.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+// ------------------------- Entry class tests ---------------------------------
+
+using namespace opentelemetry;
+using opentelemetry::common::KeyValueProperties;
+// Test constructor that takes a key-value pair
+TEST(EntryTest, KeyValueConstruction)
+{
+ opentelemetry::nostd::string_view key = "test_key";
+ opentelemetry::nostd::string_view val = "test_value";
+ KeyValueProperties::Entry e(key, val);
+
+ EXPECT_EQ(key.size(), e.GetKey().size());
+ EXPECT_EQ(key, e.GetKey());
+
+ EXPECT_EQ(val.size(), e.GetValue().size());
+ EXPECT_EQ(val, e.GetValue());
+}
+
+// Test copy constructor
+TEST(EntryTest, Copy)
+{
+ KeyValueProperties::Entry e("test_key", "test_value");
+ KeyValueProperties::Entry copy(e);
+ EXPECT_EQ(copy.GetKey(), e.GetKey());
+ EXPECT_EQ(copy.GetValue(), e.GetValue());
+}
+
+// Test assignment operator
+TEST(EntryTest, Assignment)
+{
+ KeyValueProperties::Entry e("test_key", "test_value");
+ KeyValueProperties::Entry empty;
+ empty = e;
+ EXPECT_EQ(empty.GetKey(), e.GetKey());
+ EXPECT_EQ(empty.GetValue(), e.GetValue());
+}
+
+TEST(EntryTest, SetValue)
+{
+ KeyValueProperties::Entry e("test_key", "test_value");
+ opentelemetry::nostd::string_view new_val = "new_value";
+ e.SetValue(new_val);
+
+ EXPECT_EQ(new_val.size(), e.GetValue().size());
+ EXPECT_EQ(new_val, e.GetValue());
+}
+
+// ------------------------- KeyValueStringTokenizer tests ---------------------------------
+
+using opentelemetry::common::KeyValueStringTokenizer;
+using opentelemetry::common::KeyValueStringTokenizerOptions;
+
+TEST(KVStringTokenizer, SinglePair)
+{
+ bool valid_kv;
+ nostd::string_view key, value;
+ opentelemetry::nostd::string_view str = "k1=v1";
+ KeyValueStringTokenizerOptions opts;
+ KeyValueStringTokenizer tk(str, opts);
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+ EXPECT_TRUE(valid_kv);
+ EXPECT_EQ(key, "k1");
+ EXPECT_EQ(value, "v1");
+ EXPECT_FALSE(tk.next(valid_kv, key, value));
+}
+
+TEST(KVStringTokenizer, AcceptEmptyEntries)
+{
+ bool valid_kv;
+ nostd::string_view key, value;
+ opentelemetry::nostd::string_view str = ":k1=v1::k2=v2: ";
+ KeyValueStringTokenizerOptions opts;
+ opts.member_separator = ':';
+ opts.ignore_empty_members = false;
+
+ KeyValueStringTokenizer tk(str, opts);
+ EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+ EXPECT_TRUE(valid_kv);
+ EXPECT_EQ(key, "k1");
+ EXPECT_EQ(value, "v1");
+ EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair
+ EXPECT_EQ(key, "");
+ EXPECT_EQ(value, "");
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+ EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair
+ EXPECT_FALSE(tk.next(valid_kv, key, value));
+}
+
+TEST(KVStringTokenizer, ValidPairsWithEmptyEntries)
+{
+ opentelemetry::nostd::string_view str = "k1:v1===k2:v2==";
+ bool valid_kv;
+ nostd::string_view key, value;
+ KeyValueStringTokenizerOptions opts;
+ opts.member_separator = '=';
+ opts.key_value_separator = ':';
+
+ KeyValueStringTokenizer tk(str, opts);
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+ EXPECT_TRUE(valid_kv);
+ EXPECT_EQ(key, "k1");
+ EXPECT_EQ(value, "v1");
+
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+ EXPECT_TRUE(valid_kv);
+ EXPECT_EQ(key, "k2");
+ EXPECT_EQ(value, "v2");
+
+ EXPECT_FALSE(tk.next(valid_kv, key, value));
+}
+
+TEST(KVStringTokenizer, InvalidPairs)
+{
+ opentelemetry::nostd::string_view str = "k1=v1,invalid ,, k2=v2 ,invalid";
+ KeyValueStringTokenizer tk(str);
+ bool valid_kv;
+ nostd::string_view key, value;
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+
+ EXPECT_TRUE(valid_kv);
+ EXPECT_EQ(key, "k1");
+ EXPECT_EQ(value, "v1");
+
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+ EXPECT_FALSE(valid_kv);
+
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+ EXPECT_TRUE(valid_kv);
+ EXPECT_EQ(key, "k2");
+ EXPECT_EQ(value, "v2");
+
+ EXPECT_TRUE(tk.next(valid_kv, key, value));
+ EXPECT_FALSE(valid_kv);
+
+ EXPECT_FALSE(tk.next(valid_kv, key, value));
+}
+
+TEST(KVStringTokenizer, NumTokens)
+{
+ struct
+ {
+ const char *input;
+ size_t expected;
+ } testcases[] = {{"k1=v1", 1},
+ {" ", 1},
+ {"k1=v1,k2=v2,k3=v3", 3},
+ {"k1=v1,", 1},
+ {"k1=v1,k2=v2,invalidmember", 3},
+ {"", 0}};
+ for (auto &testcase : testcases)
+ {
+ KeyValueStringTokenizer tk(testcase.input);
+ EXPECT_EQ(tk.NumTokens(), testcase.expected);
+ }
+}
+
+//------------------------- KeyValueProperties tests ---------------------------------
+
+TEST(KeyValueProperties, PopulateKVIterableContainer)
+{
+ std::vector<std::pair<std::string, std::string>> kv_pairs = {{"k1", "v1"}, {"k2", "v2"}};
+
+ auto kv_properties = KeyValueProperties(kv_pairs);
+ EXPECT_EQ(kv_properties.Size(), 2);
+
+ std::string value;
+ bool present = kv_properties.GetValue("k1", value);
+ EXPECT_TRUE(present);
+ EXPECT_EQ(value, "v1");
+
+ present = kv_properties.GetValue("k2", value);
+ EXPECT_TRUE(present);
+ EXPECT_EQ(value, "v2");
+}
+
+TEST(KeyValueProperties, AddEntry)
+{
+ auto kv_properties = KeyValueProperties(1);
+ kv_properties.AddEntry("k1", "v1");
+ std::string value;
+ bool present = kv_properties.GetValue("k1", value);
+ EXPECT_TRUE(present);
+ EXPECT_EQ(value, "v1");
+
+ kv_properties.AddEntry("k2", "v2"); // entry will not be added as max size reached.
+ EXPECT_EQ(kv_properties.Size(), 1);
+ present = kv_properties.GetValue("k2", value);
+ EXPECT_FALSE(present);
+}
+
+TEST(KeyValueProperties, GetValue)
+{
+ auto kv_properties = KeyValueProperties(1);
+ kv_properties.AddEntry("k1", "v1");
+ std::string value;
+ bool present = kv_properties.GetValue("k1", value);
+ EXPECT_TRUE(present);
+ EXPECT_EQ(value, "v1");
+
+ present = kv_properties.GetValue("k3", value);
+ EXPECT_FALSE(present);
+}
+
+TEST(KeyValueProperties, GetAllEntries)
+{
+ std::vector<std::pair<std::string, std::string>> kv_pairs = {
+ {"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}};
+ const size_t kNumPairs = 3;
+ opentelemetry::nostd::string_view keys[kNumPairs] = {"k1", "k2", "k3"};
+ opentelemetry::nostd::string_view values[kNumPairs] = {"v1", "v2", "v3"};
+ auto kv_properties = KeyValueProperties(kv_pairs);
+
+ size_t index = 0;
+ kv_properties.GetAllEntries(
+ [&keys, &values, &index](nostd::string_view key, nostd::string_view value) {
+ EXPECT_EQ(key, keys[index]);
+ EXPECT_EQ(value, values[index]);
+ index++;
+ return true;
+ });
+
+ EXPECT_EQ(index, kNumPairs);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/spinlock_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/api/test/common/spinlock_benchmark.cc
new file mode 100644
index 000000000..07579579c
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/spinlock_benchmark.cc
@@ -0,0 +1,152 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/common/spin_lock_mutex.h"
+
+#include <benchmark/benchmark.h>
+#include <mutex>
+
+namespace
+{
+using opentelemetry::common::SpinLockMutex;
+
+constexpr int TightLoopLocks = 10000;
+
+// Runs a thrash-test where we spin up N threads, each of which will
+// attempt to lock-mutate-unlock a total of `TightLoopLocks` times.
+//
+// lock: A lambda denoting how to lock. Accepts a reference to `SpinLockType`.
+// unlock: A lambda denoting how to unlock. Accepts a reference to `SpinLockType`.
+template <typename SpinLockType, typename LockF, typename UnlockF>
+inline void SpinThrash(benchmark::State &s, SpinLockType &spinlock, LockF lock, UnlockF unlock)
+{
+ auto num_threads = s.range(0);
+ // Value we will increment, fighting over a spinlock.
+ // The contention is meant to be brief, as close to our expected
+ // use cases of "updating pointers" or "pushing an event onto a buffer".
+ std::int64_t value = 0;
+
+ std::vector<std::thread> threads;
+ threads.reserve(num_threads);
+
+ // Timing loop
+ for (auto _ : s)
+ {
+ for (auto i = 0; i < num_threads; i++)
+ {
+ threads.emplace_back([&] {
+ // Increment value once each time the lock is acquired. Spin a few times
+ // to ensure maximum thread contention.
+ for (int i = 0; i < TightLoopLocks; i++)
+ {
+ lock(spinlock);
+ value++;
+ unlock(spinlock);
+ }
+ });
+ }
+ // Join threads
+ for (auto &thread : threads)
+ thread.join();
+ threads.clear();
+ }
+}
+
+// Benchmark of full spin-lock implementation.
+static void BM_SpinLockThrashing(benchmark::State &s)
+{
+ SpinLockMutex spinlock;
+ SpinThrash(
+ s, spinlock, [](SpinLockMutex &m) { m.lock(); }, [](SpinLockMutex &m) { m.unlock(); });
+}
+
+// Naive `while(try_lock()) {}` implementation of lock.
+static void BM_NaiveSpinLockThrashing(benchmark::State &s)
+{
+ SpinLockMutex spinlock;
+ SpinThrash(
+ s, spinlock,
+ [](SpinLockMutex &m) {
+ while (!m.try_lock())
+ {
+ // Left this comment to keep the same format on old and new versions of clang-format
+ }
+ },
+ [](SpinLockMutex &m) { m.unlock(); });
+}
+
+// Simple `while(try_lock()) { yield-processor }`
+static void BM_ProcYieldSpinLockThrashing(benchmark::State &s)
+{
+ SpinLockMutex spinlock;
+ SpinThrash<SpinLockMutex>(
+ s, spinlock,
+ [](SpinLockMutex &m) {
+ while (!m.try_lock())
+ {
+#if defined(_MSC_VER)
+ YieldProcessor();
+#elif defined(__i386__) || defined(__x86_64__)
+# if defined(__clang__)
+ _mm_pause();
+# else
+ __builtin_ia32_pause();
+# endif
+#elif defined(__arm__)
+ __asm__ volatile("yield" ::: "memory");
+#endif
+ }
+ },
+ [](SpinLockMutex &m) { m.unlock(); });
+}
+
+// SpinLock thrashing with thread::yield().
+static void BM_ThreadYieldSpinLockThrashing(benchmark::State &s)
+{
+ std::atomic_flag mutex = ATOMIC_FLAG_INIT;
+ SpinThrash<std::atomic_flag>(
+ s, mutex,
+ [](std::atomic_flag &l) {
+ uint32_t try_count = 0;
+ while (l.test_and_set(std::memory_order_acq_rel))
+ {
+ ++try_count;
+ if (try_count % 32)
+ {
+ std::this_thread::yield();
+ }
+ }
+ std::this_thread::yield();
+ },
+ [](std::atomic_flag &l) { l.clear(std::memory_order_release); });
+}
+
+// Run the benchmarks at 2x thread/core and measure the amount of time to thrash around.
+BENCHMARK(BM_SpinLockThrashing)
+ ->RangeMultiplier(2)
+ ->Range(1, std::thread::hardware_concurrency())
+ ->MeasureProcessCPUTime()
+ ->UseRealTime()
+ ->Unit(benchmark::kMillisecond);
+BENCHMARK(BM_ProcYieldSpinLockThrashing)
+ ->RangeMultiplier(2)
+ ->Range(1, std::thread::hardware_concurrency())
+ ->MeasureProcessCPUTime()
+ ->UseRealTime()
+ ->Unit(benchmark::kMillisecond);
+BENCHMARK(BM_NaiveSpinLockThrashing)
+ ->RangeMultiplier(2)
+ ->Range(1, std::thread::hardware_concurrency())
+ ->MeasureProcessCPUTime()
+ ->UseRealTime()
+ ->Unit(benchmark::kMillisecond);
+BENCHMARK(BM_ThreadYieldSpinLockThrashing)
+ ->RangeMultiplier(2)
+ ->Range(1, std::thread::hardware_concurrency())
+ ->MeasureProcessCPUTime()
+ ->UseRealTime()
+ ->Unit(benchmark::kMillisecond);
+
+} // namespace
+
+BENCHMARK_MAIN();
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/string_util_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/common/string_util_test.cc
new file mode 100644
index 000000000..da2e63511
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/string_util_test.cc
@@ -0,0 +1,47 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include <gtest/gtest.h>
+#include <opentelemetry/common/string_util.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+// ------------------------- StringUtil class tests ---------------------------------
+
+using opentelemetry::common::StringUtil;
+
+TEST(StringUtilTest, TrimStringWithIndex)
+{
+ struct
+ {
+ const char *input;
+ const char *expected;
+ } testcases[] = {{"k1=v1", "k1=v1"}, {"k1=v1,k2=v2, k3=v3", "k1=v1,k2=v2, k3=v3"},
+ {" k1=v1", "k1=v1"}, {"k1=v1 ", "k1=v1"},
+ {" k1=v1 ", "k1=v1"}, {" ", ""}};
+ for (auto &testcase : testcases)
+ {
+ EXPECT_EQ(StringUtil::Trim(testcase.input, 0, strlen(testcase.input) - 1), testcase.expected);
+ }
+}
+
+TEST(StringUtilTest, TrimString)
+{
+ struct
+ {
+ const char *input;
+ const char *expected;
+ } testcases[] = {{"k1=v1", "k1=v1"},
+ {"k1=v1,k2=v2, k3=v3", "k1=v1,k2=v2, k3=v3"},
+ {" k1=v1", "k1=v1"},
+ {"k1=v1 ", "k1=v1"},
+ {" k1=v1 ", "k1=v1"},
+ {" ", ""},
+ {"", ""}};
+ for (auto &testcase : testcases)
+ {
+ EXPECT_EQ(StringUtil::Trim(testcase.input), testcase.expected);
+ }
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/context/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/context/BUILD
new file mode 100644
index 000000000..f1a6ac163
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/context/BUILD
@@ -0,0 +1,31 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "context_test",
+ srcs = [
+ "context_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "runtime_context_test",
+ srcs = [
+ "runtime_context_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/context/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/context/CMakeLists.txt
new file mode 100644
index 000000000..e01e24eed
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/context/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_subdirectory(propagation)
+
+include(GoogleTest)
+
+foreach(testname context_test runtime_context_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX context.
+ TEST_LIST ${testname})
+endforeach()
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/context/context_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/context/context_test.cc
new file mode 100644
index 000000000..975e11f8c
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/context/context_test.cc
@@ -0,0 +1,147 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/context/context.h"
+
+#include <map>
+
+#include <gtest/gtest.h>
+
+using namespace opentelemetry;
+
+// Tests that the context constructor accepts an std::map.
+TEST(ContextTest, ContextIterableAcceptsMap)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ context::Context test_context = context::Context(map_test);
+}
+
+// Tests that the GetValue method returns the expected value.
+TEST(ContextTest, ContextGetValueReturnsExpectedValue)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123},
+ {"foo_key", (int64_t)456}};
+ const context::Context test_context = context::Context(map_test);
+ EXPECT_EQ(nostd::get<int64_t>(test_context.GetValue("test_key")), 123);
+ EXPECT_EQ(nostd::get<int64_t>(test_context.GetValue("foo_key")), 456);
+}
+
+// Tests that the SetValues method accepts an std::map.
+TEST(ContextTest, ContextSetValuesAcceptsMap)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ std::map<std::string, context::ContextValue> map_test_write = {{"foo_key", (int64_t)456}};
+
+ context::Context test_context = context::Context(map_test);
+ context::Context foo_context = test_context.SetValues(map_test_write);
+
+ EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("test_key")), 123);
+ EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("foo_key")), 456);
+}
+
+// Tests that the SetValues method accepts a nostd::string_view and
+// context::ContextValue.
+TEST(ContextTest, ContextSetValuesAcceptsStringViewContextValue)
+{
+ nostd::string_view string_view_test = "string_view";
+ context::ContextValue context_value_test = (int64_t)123;
+
+ context::Context test_context = context::Context(string_view_test, context_value_test);
+ context::Context foo_context = test_context.SetValue(string_view_test, context_value_test);
+
+ EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue(string_view_test)), 123);
+}
+
+// Tests that the original context does not change when a value is
+// written to it.
+TEST(ContextTest, ContextImmutability)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+
+ context::Context context_test = context::Context(map_test);
+ context::Context context_foo = context_test.SetValue("foo_key", (int64_t)456);
+
+ EXPECT_FALSE(nostd::holds_alternative<int64_t>(context_test.GetValue("foo_key")));
+}
+
+// Tests that writing the same to a context overwrites the original value.
+TEST(ContextTest, ContextKeyOverwrite)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+
+ context::Context context_test = context::Context(map_test);
+ context::Context context_foo = context_test.SetValue("test_key", (int64_t)456);
+
+ EXPECT_EQ(nostd::get<int64_t>(context_foo.GetValue("test_key")), 456);
+}
+
+// Tests that the new Context Objects inherits the keys and values
+// of the original context object.
+TEST(ContextTest, ContextInheritance)
+{
+ using M = std::map<std::string, context::ContextValue>;
+
+ M m1 = {{"test_key", (int64_t)123}, {"foo_key", (int64_t)321}};
+ M m2 = {{"other_key", (int64_t)789}, {"another_key", (int64_t)987}};
+
+ context::Context test_context = context::Context(m1);
+ context::Context foo_context = test_context.SetValues(m2);
+
+ EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("test_key")), 123);
+ EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("foo_key")), 321);
+ EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("other_key")), 789);
+ EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("another_key")), 987);
+
+ EXPECT_TRUE(nostd::holds_alternative<nostd::monostate>(test_context.GetValue("other_key")));
+ EXPECT_TRUE(nostd::holds_alternative<nostd::monostate>(test_context.GetValue("another_key")));
+}
+
+// Tests that copying a context copies the key value pairs as expected.
+TEST(ContextTest, ContextCopyOperator)
+{
+ std::map<std::string, context::ContextValue> test_map = {
+ {"test_key", (int64_t)123}, {"foo_key", (int64_t)456}, {"other_key", (int64_t)789}};
+
+ context::Context test_context = context::Context(test_map);
+ context::Context copied_context = test_context;
+
+ EXPECT_EQ(nostd::get<int64_t>(copied_context.GetValue("test_key")), 123);
+ EXPECT_EQ(nostd::get<int64_t>(copied_context.GetValue("foo_key")), 456);
+ EXPECT_EQ(nostd::get<int64_t>(copied_context.GetValue("other_key")), 789);
+}
+
+// Tests that the Context accepts an empty map.
+TEST(ContextTest, ContextEmptyMap)
+{
+ std::map<std::string, context::ContextValue> map_test = {};
+ context::Context test_context = context::Context(map_test);
+}
+
+// Tests that if a key exists within a context has key will return true
+// false if not.
+TEST(ContextTest, ContextHasKey)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ const context::Context context_test = context::Context(map_test);
+ EXPECT_TRUE(context_test.HasKey("test_key"));
+ EXPECT_FALSE(context_test.HasKey("foo_key"));
+}
+
+// Tests that a copied context returns true when compared
+TEST(ContextTest, ContextCopyCompare)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ context::Context context_test = context::Context(map_test);
+ context::Context copied_test = context_test;
+ EXPECT_TRUE(context_test == copied_test);
+}
+
+// Tests that two differently constructed contexts return false when compared
+TEST(ContextTest, ContextDiffCompare)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ std::map<std::string, context::ContextValue> map_foo = {{"foo_key", (int64_t)123}};
+ context::Context context_test = context::Context(map_test);
+ context::Context foo_test = context::Context(map_foo);
+ EXPECT_FALSE(context_test == foo_test);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/BUILD
new file mode 100644
index 000000000..388b5e0d3
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/BUILD
@@ -0,0 +1,16 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "composite_propagator_test",
+ srcs = [
+ "composite_propagator_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/CMakeLists.txt
new file mode 100644
index 000000000..74a8176a2
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/CMakeLists.txt
@@ -0,0 +1,9 @@
+foreach(testname composite_propagator_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX trace.
+ TEST_LIST ${testname})
+endforeach()
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/composite_propagator_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/composite_propagator_test.cc
new file mode 100644
index 000000000..918f8cedd
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/composite_propagator_test.cc
@@ -0,0 +1,124 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/trace/scope.h"
+#include "opentelemetry/trace/span.h"
+#include "opentelemetry/trace/span_context.h"
+
+#include "opentelemetry/context/propagation/composite_propagator.h"
+#include "opentelemetry/context/propagation/text_map_propagator.h"
+#include "opentelemetry/trace/default_span.h"
+#include "opentelemetry/trace/propagation/b3_propagator.h"
+#include "opentelemetry/trace/propagation/http_trace_context.h"
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <gtest/gtest.h>
+
+using namespace opentelemetry;
+
+template <typename T>
+static std::string Hex(const T &id_item)
+{
+ char buf[T::kSize * 2];
+ id_item.ToLowerBase16(buf);
+ return std::string(buf, sizeof(buf));
+}
+
+class TextMapCarrierTest : public context::propagation::TextMapCarrier
+{
+public:
+ virtual nostd::string_view Get(nostd::string_view key) const noexcept override
+ {
+ auto it = headers_.find(std::string(key));
+ if (it != headers_.end())
+ {
+ return nostd::string_view(it->second);
+ }
+ return "";
+ }
+ virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
+ {
+ headers_[std::string(key)] = std::string(value);
+ }
+
+ std::map<std::string, std::string> headers_;
+};
+
+class CompositePropagatorTest : public ::testing::Test
+{
+
+public:
+ CompositePropagatorTest()
+ {
+ std::vector<std::unique_ptr<context::propagation::TextMapPropagator>> propogator_list = {};
+ std::unique_ptr<context::propagation::TextMapPropagator> w3c_propogator(
+ new trace::propagation::HttpTraceContext());
+ std::unique_ptr<context::propagation::TextMapPropagator> b3_propogator(
+ new trace::propagation::B3Propagator());
+ propogator_list.push_back(std::move(w3c_propogator));
+ propogator_list.push_back(std::move(b3_propogator));
+
+ composite_propagator_ =
+ new context::propagation::CompositePropagator(std::move(propogator_list));
+ }
+
+ ~CompositePropagatorTest() { delete composite_propagator_; }
+
+protected:
+ context::propagation::CompositePropagator *composite_propagator_;
+};
+
+TEST_F(CompositePropagatorTest, Extract)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {
+ {"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"},
+ {"b3", "80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90"}};
+ context::Context ctx1 = context::Context{};
+
+ context::Context ctx2 = composite_propagator_->Extract(carrier, ctx1);
+
+ auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
+ EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
+
+ auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
+
+ // confirm last propagator in composite propagator list (B3 here) wins for same key
+ // ("active_span" here).
+ EXPECT_EQ(Hex(span->GetContext().trace_id()), "80f198ee56343ba864fe8b2a57d3eff7");
+ EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
+ EXPECT_EQ(span->GetContext().IsSampled(), true);
+ EXPECT_EQ(span->GetContext().IsRemote(), true);
+}
+
+TEST_F(CompositePropagatorTest, Inject)
+{
+ TextMapCarrierTest carrier;
+ constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+ trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span},
+ trace::TraceFlags{true}, false};
+ nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}};
+
+ // Set `sp` as the currently active span, which must be used by `Inject`.
+ trace::Scope scoped_span{sp};
+
+ composite_propagator_->Inject(carrier, context::RuntimeContext::GetCurrent());
+ EXPECT_EQ(carrier.headers_["traceparent"],
+ "00-0102030405060708090a0b0c0d0e0f10-0102030405060708-01");
+ EXPECT_EQ(carrier.headers_["b3"], "0102030405060708090a0b0c0d0e0f10-0102030405060708-1");
+
+ std::vector<std::string> fields;
+ composite_propagator_->Fields([&fields](nostd::string_view field) {
+ fields.push_back(field.data());
+ return true;
+ });
+ EXPECT_EQ(fields.size(), 3);
+ EXPECT_EQ(fields[0], trace::propagation::kTraceParent);
+ EXPECT_EQ(fields[1], trace::propagation::kTraceState);
+ EXPECT_EQ(fields[2], trace::propagation::kB3CombinedHeader);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/context/runtime_context_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/context/runtime_context_test.cc
new file mode 100644
index 000000000..e85fc6350
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/context/runtime_context_test.cc
@@ -0,0 +1,135 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/context/runtime_context.h"
+#include "opentelemetry/context/context.h"
+
+#include <gtest/gtest.h>
+
+using namespace opentelemetry;
+
+// Tests that GetCurrent returns the current context
+TEST(RuntimeContextTest, GetCurrent)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ context::Context test_context = context::Context(map_test);
+ auto old_context = context::RuntimeContext::Attach(test_context);
+ EXPECT_EQ(context::RuntimeContext::GetCurrent(), test_context);
+}
+
+// Tests that detach resets the context to the previous context
+TEST(RuntimeContextTest, Detach)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ context::Context test_context = context::Context(map_test);
+ context::Context foo_context = context::Context(map_test);
+
+ auto test_context_token = context::RuntimeContext::Attach(test_context);
+ auto foo_context_token = context::RuntimeContext::Attach(foo_context);
+
+ foo_context_token.reset();
+ EXPECT_EQ(context::RuntimeContext::GetCurrent(), test_context);
+ test_context_token.reset();
+}
+
+// Tests that detach returns false when the wrong context is provided
+TEST(RuntimeContextTest, DetachWrongContext)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ context::Context test_context = context::Context(map_test);
+ auto test_context_token = context::RuntimeContext::Attach(test_context);
+ EXPECT_TRUE(context::RuntimeContext::Detach(*test_context_token));
+ EXPECT_FALSE(context::RuntimeContext::Detach(*test_context_token));
+}
+
+// Tests that the ThreadLocalContext can handle three attached contexts
+TEST(RuntimeContextTest, ThreeAttachDetach)
+{
+ std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
+ context::Context test_context = context::Context(map_test);
+ context::Context foo_context = context::Context(map_test);
+ context::Context other_context = context::Context(map_test);
+ auto test_context_token = context::RuntimeContext::Attach(test_context);
+ auto foo_context_token = context::RuntimeContext::Attach(foo_context);
+ auto other_context_token = context::RuntimeContext::Attach(other_context);
+
+ EXPECT_TRUE(context::RuntimeContext::Detach(*other_context_token));
+ EXPECT_TRUE(context::RuntimeContext::Detach(*foo_context_token));
+ EXPECT_TRUE(context::RuntimeContext::Detach(*test_context_token));
+}
+
+// Tests that SetValue returns a context with the passed in data and the
+// RuntimeContext data when a context is not passed into the
+// RuntimeContext::SetValue method.
+TEST(RuntimeContextTest, SetValueRuntimeContext)
+{
+ context::Context foo_context = context::Context("foo_key", (int64_t)596);
+ auto old_context_token = context::RuntimeContext::Attach(foo_context);
+ context::Context test_context = context::RuntimeContext::SetValue("test_key", (int64_t)123);
+ EXPECT_EQ(nostd::get<int64_t>(test_context.GetValue("test_key")), 123);
+ EXPECT_EQ(nostd::get<int64_t>(test_context.GetValue("foo_key")), 596);
+}
+
+// Tests that SetValue returns a context with the passed in data and the
+// passed in context data when a context* is passed into the
+// RuntimeContext::SetValue method.
+TEST(RuntimeContextTest, SetValueOtherContext)
+{
+ context::Context foo_context = context::Context("foo_key", (int64_t)596);
+ context::Context test_context =
+ context::RuntimeContext::SetValue("test_key", (int64_t)123, &foo_context);
+ EXPECT_EQ(nostd::get<int64_t>(test_context.GetValue("test_key")), 123);
+ EXPECT_EQ(nostd::get<int64_t>(test_context.GetValue("foo_key")), 596);
+}
+
+// Tests that SetValue returns the ContextValue associated with the
+// passed in string and the current Runtime Context
+TEST(RuntimeContextTest, GetValueRuntimeContext)
+{
+ context::Context foo_context = context::Context("foo_key", (int64_t)596);
+ auto old_context_token = context::RuntimeContext::Attach(foo_context);
+ EXPECT_EQ(nostd::get<int64_t>(context::RuntimeContext::GetValue("foo_key")), 596);
+}
+
+// Tests that SetValue returns the ContextValue associated with the
+// passed in string and the passed in context
+TEST(RuntimeContextTest, GetValueOtherContext)
+{
+ context::Context foo_context = context::Context("foo_key", (int64_t)596);
+ EXPECT_EQ(nostd::get<int64_t>(context::RuntimeContext::GetValue("foo_key", &foo_context)), 596);
+}
+
+// Test that any possible order of context detaching doesn't mess up the stack.
+TEST(RuntimeContextTest, DetachOutOfOrder)
+{
+ std::vector<size_t> indices;
+ indices.push_back(0);
+ indices.push_back(1);
+ indices.push_back(2);
+ indices.push_back(3);
+
+ std::vector<context::Context> contexts;
+ for (auto i : indices)
+ {
+ contexts.push_back(context::Context("index", (int64_t)i));
+ }
+
+ do
+ {
+ std::vector<nostd::unique_ptr<context::Token>> tokens;
+
+ for (auto &c : contexts)
+ {
+ tokens.push_back(context::RuntimeContext::Attach(c));
+ }
+
+ for (size_t i : indices)
+ {
+ auto token = std::move(tokens.at(i));
+ context::RuntimeContext::Detach(*token);
+ }
+
+ EXPECT_EQ(context::RuntimeContext::GetCurrent(), context::Context());
+
+ } while (std::next_permutation(indices.begin(), indices.end()));
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/core/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/core/BUILD
new file mode 100644
index 000000000..99fcfaeca
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/core/BUILD
@@ -0,0 +1,14 @@
+cc_test(
+ name = "timestamp_test",
+ srcs = [
+ "timestamp_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/core/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/core/CMakeLists.txt
new file mode 100644
index 000000000..7fead491e
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/core/CMakeLists.txt
@@ -0,0 +1,9 @@
+include(GoogleTest)
+
+add_executable(timestamp_test timestamp_test.cc)
+target_link_libraries(timestamp_test ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+gtest_add_tests(
+ TARGET timestamp_test
+ TEST_PREFIX trace.
+ TEST_LIST timestamp_test)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/core/timestamp_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/core/timestamp_test.cc
new file mode 100644
index 000000000..8efc0215b
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/core/timestamp_test.cc
@@ -0,0 +1,67 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/common/timestamp.h"
+
+#include <gtest/gtest.h>
+
+using opentelemetry::common::SteadyTimestamp;
+using opentelemetry::common::SystemTimestamp;
+
+template <class Timestamp>
+static bool AreNearlyEqual(const Timestamp &t1, const Timestamp &t2) noexcept
+{
+ return std::abs(std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count()) < 2;
+}
+
+TEST(SystemTimestampTest, Construction)
+{
+ auto now_system = std::chrono::system_clock::now();
+
+ SystemTimestamp t1;
+ EXPECT_EQ(t1.time_since_epoch(), std::chrono::nanoseconds{0});
+
+ SystemTimestamp t2{now_system};
+ EXPECT_TRUE(AreNearlyEqual(now_system, static_cast<std::chrono::system_clock::time_point>(t2)));
+ EXPECT_EQ(std::chrono::duration_cast<std::chrono::nanoseconds>(now_system.time_since_epoch()),
+ t2.time_since_epoch());
+}
+
+TEST(SystemTimestampTest, Comparison)
+{
+ SystemTimestamp t1;
+ SystemTimestamp t2;
+ SystemTimestamp t3{std::chrono::nanoseconds{2}};
+
+ EXPECT_EQ(t1, t1);
+ EXPECT_EQ(t1, t2);
+ EXPECT_EQ(t2, t1);
+ EXPECT_NE(t1, t3);
+ EXPECT_NE(t3, t1);
+}
+
+TEST(SteadyTimestampTest, Construction)
+{
+ auto now_steady = std::chrono::steady_clock::now();
+
+ SteadyTimestamp t1;
+ EXPECT_EQ(t1.time_since_epoch(), std::chrono::nanoseconds{0});
+
+ SteadyTimestamp t2{now_steady};
+ EXPECT_TRUE(AreNearlyEqual(now_steady, static_cast<std::chrono::steady_clock::time_point>(t2)));
+ EXPECT_EQ(std::chrono::duration_cast<std::chrono::nanoseconds>(now_steady.time_since_epoch()),
+ t2.time_since_epoch());
+}
+
+TEST(SteadyTimestampTest, Comparison)
+{
+ SteadyTimestamp t1;
+ SteadyTimestamp t2;
+ SteadyTimestamp t3{std::chrono::nanoseconds{2}};
+
+ EXPECT_EQ(t1, t1);
+ EXPECT_EQ(t1, t2);
+ EXPECT_EQ(t2, t1);
+ EXPECT_NE(t1, t3);
+ EXPECT_NE(t3, t1);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/logs/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/logs/BUILD
new file mode 100644
index 000000000..34fda18db
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/logs/BUILD
@@ -0,0 +1,33 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "provider_test",
+ srcs = [
+ "provider_test.cc",
+ ],
+ tags = [
+ "api",
+ "logs",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "logger_test",
+ srcs = [
+ "logger_test.cc",
+ ],
+ tags = [
+ "api",
+ "logs",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/logs/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/logs/CMakeLists.txt
new file mode 100644
index 000000000..a5f9c0408
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/logs/CMakeLists.txt
@@ -0,0 +1,9 @@
+foreach(testname provider_test logger_test)
+ add_executable(logs_api_${testname} "${testname}.cc")
+ target_link_libraries(logs_api_${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET logs_api_${testname}
+ TEST_PREFIX logs.
+ TEST_LIST logs_api_${testname})
+endforeach()
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/logs/logger_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/logs/logger_test.cc
new file mode 100644
index 000000000..07480ef44
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/logs/logger_test.cc
@@ -0,0 +1,165 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifdef ENABLE_LOGS_PREVIEW
+
+# include <gtest/gtest.h>
+# include <array>
+
+# include "opentelemetry/common/timestamp.h"
+# include "opentelemetry/logs/logger.h"
+# include "opentelemetry/logs/provider.h"
+# include "opentelemetry/nostd/shared_ptr.h"
+
+using opentelemetry::logs::Logger;
+using opentelemetry::logs::LoggerProvider;
+using opentelemetry::logs::Provider;
+using opentelemetry::logs::Severity;
+using opentelemetry::nostd::shared_ptr;
+using opentelemetry::nostd::span;
+using opentelemetry::nostd::string_view;
+namespace common = opentelemetry::common;
+namespace nostd = opentelemetry::nostd;
+namespace trace = opentelemetry::trace;
+
+// Check that the default logger is a noop logger instance
+TEST(Logger, GetLoggerDefault)
+{
+ auto lp = Provider::GetLoggerProvider();
+ const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
+ auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url);
+ auto name = logger->GetName();
+ EXPECT_NE(nullptr, logger);
+ EXPECT_EQ(name, "noop logger");
+}
+
+// Test the two additional overloads for GetLogger()
+TEST(Logger, GetNoopLoggerNameWithArgs)
+{
+ auto lp = Provider::GetLoggerProvider();
+
+ // GetLogger(name, list(args))
+ std::array<string_view, 1> sv{"string"};
+ span<string_view> args{sv};
+ const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
+ lp->GetLogger("NoopLoggerWithArgs", args, "opentelelemtry_library", "", schema_url);
+
+ // GetLogger(name, string options)
+ lp->GetLogger("NoopLoggerWithOptions", "options", "opentelelemtry_library", "", schema_url);
+}
+
+// Test the Log() overloads
+TEST(Logger, LogMethodOverloads)
+{
+ auto lp = Provider::GetLoggerProvider();
+ const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
+ auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url);
+
+ // Create a map to test the logs with
+ std::map<std::string, std::string> m = {{"key1", "value1"}};
+
+ // Log overloads
+ logger->Log(Severity::kTrace, "Test log message");
+ logger->Log(Severity::kInfo, "Test log message");
+ logger->Log(Severity::kDebug, m);
+ logger->Log(Severity::kWarn, "Logging a map", m);
+ logger->Log(Severity::kError, {{"key1", "value 1"}, {"key2", 2}});
+ logger->Log(Severity::kFatal, "Logging an initializer list", {{"key1", "value 1"}, {"key2", 2}});
+
+ // Deprecated Log overloads
+ logger->Log(Severity::kTrace, "Log name", "Test log message");
+ logger->Log(Severity::kWarn, "Log name", "Logging a map", m, {}, {}, {},
+ std::chrono::system_clock::now());
+ logger->Log(Severity::kError, "Log name", "Logging a map", {{"key1", "value 1"}, {"key2", 2}}, {},
+ {}, {}, std::chrono::system_clock::now());
+ logger->Trace("Log name", "Test log message");
+ logger->Debug("Log name", "Test log message");
+ logger->Info("Log name", "Test log message");
+ logger->Warn("Log name", "Test log message");
+ logger->Error("Log name", "Test log message");
+ logger->Fatal("Log name", "Test log message");
+
+ // Severity methods
+ logger->Trace("Test log message");
+ logger->Trace("Test log message", m);
+ logger->Trace("Test log message", {{"key1", "value 1"}, {"key2", 2}});
+ logger->Trace(m);
+ logger->Trace({{"key1", "value 1"}, {"key2", 2}});
+ logger->Debug("Test log message");
+ logger->Debug("Test log message", m);
+ logger->Debug("Test log message", {{"key1", "value 1"}, {"key2", 2}});
+ logger->Debug(m);
+ logger->Debug({{"key1", "value 1"}, {"key2", 2}});
+ logger->Info("Test log message");
+ logger->Info("Test log message", m);
+ logger->Info("Test log message", {{"key1", "value 1"}, {"key2", 2}});
+ logger->Info(m);
+ logger->Info({{"key1", "value 1"}, {"key2", 2}});
+ logger->Warn("Test log message");
+ logger->Warn("Test log message", m);
+ logger->Warn("Test log message", {{"key1", "value 1"}, {"key2", 2}});
+ logger->Warn(m);
+ logger->Warn({{"key1", "value 1"}, {"key2", 2}});
+ logger->Error("Test log message");
+ logger->Error("Test log message", m);
+ logger->Error("Test log message", {{"key1", "value 1"}, {"key2", 2}});
+ logger->Error(m);
+ logger->Error({{"key1", "value 1"}, {"key2", 2}});
+ logger->Fatal("Test log message");
+ logger->Fatal("Test log message", m);
+ logger->Fatal("Test log message", {{"key1", "value 1"}, {"key2", 2}});
+ logger->Fatal(m);
+ logger->Fatal({{"key1", "value 1"}, {"key2", 2}});
+}
+
+// Define a basic Logger class
+class TestLogger : public Logger
+{
+ const nostd::string_view GetName() noexcept override { return "test logger"; }
+
+ void Log(Severity severity,
+ string_view body,
+ const common::KeyValueIterable &attributes,
+ trace::TraceId trace_id,
+ trace::SpanId span_id,
+ trace::TraceFlags trace_flags,
+ common::SystemTimestamp timestamp) noexcept override
+ {}
+};
+
+// Define a basic LoggerProvider class that returns an instance of the logger class defined above
+class TestProvider : public LoggerProvider
+{
+ nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name,
+ nostd::string_view options,
+ nostd::string_view library_name,
+ nostd::string_view library_version = "",
+ nostd::string_view schema_url = "") override
+ {
+ return shared_ptr<Logger>(new TestLogger());
+ }
+
+ nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name,
+ nostd::span<nostd::string_view> args,
+ nostd::string_view library_name,
+ nostd::string_view library_version = "",
+ nostd::string_view schema_url = "") override
+ {
+ return shared_ptr<Logger>(new TestLogger());
+ }
+};
+
+TEST(Logger, PushLoggerImplementation)
+{
+ // Push the new loggerprovider class into the global singleton
+ auto test_provider = shared_ptr<LoggerProvider>(new TestProvider());
+ Provider::SetLoggerProvider(test_provider);
+
+ auto lp = Provider::GetLoggerProvider();
+
+ // Check that the implementation was pushed by calling TestLogger's GetName()
+ nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"};
+ auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url);
+ ASSERT_EQ("test logger", logger->GetName());
+}
+#endif
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/logs/provider_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/logs/provider_test.cc
new file mode 100644
index 000000000..64a6b0a86
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/logs/provider_test.cc
@@ -0,0 +1,77 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifdef ENABLE_LOGS_PREVIEW
+
+# include <gtest/gtest.h>
+# include <array>
+
+# include "opentelemetry/logs/provider.h"
+# include "opentelemetry/nostd/shared_ptr.h"
+
+using opentelemetry::logs::Logger;
+using opentelemetry::logs::LoggerProvider;
+using opentelemetry::logs::Provider;
+using opentelemetry::nostd::shared_ptr;
+namespace nostd = opentelemetry::nostd;
+
+class TestProvider : public LoggerProvider
+{
+ nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name,
+ nostd::string_view options,
+ nostd::string_view library_name,
+ nostd::string_view library_version = "",
+ nostd::string_view schema_url = "") override
+ {
+ return shared_ptr<Logger>(nullptr);
+ }
+
+ nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name,
+ nostd::span<nostd::string_view> args,
+ nostd::string_view library_name,
+ nostd::string_view library_version = "",
+ nostd::string_view schema_url = "") override
+ {
+ return shared_ptr<Logger>(nullptr);
+ }
+};
+
+TEST(Provider, GetLoggerProviderDefault)
+{
+ auto tf = Provider::GetLoggerProvider();
+ EXPECT_NE(nullptr, tf);
+}
+
+TEST(Provider, SetLoggerProvider)
+{
+ auto tf = shared_ptr<LoggerProvider>(new TestProvider());
+ Provider::SetLoggerProvider(tf);
+ ASSERT_EQ(tf, Provider::GetLoggerProvider());
+}
+
+TEST(Provider, MultipleLoggerProviders)
+{
+ auto tf = shared_ptr<LoggerProvider>(new TestProvider());
+ Provider::SetLoggerProvider(tf);
+ auto tf2 = shared_ptr<LoggerProvider>(new TestProvider());
+ Provider::SetLoggerProvider(tf2);
+
+ ASSERT_NE(Provider::GetLoggerProvider(), tf);
+}
+
+TEST(Provider, GetLogger)
+{
+ auto tf = shared_ptr<LoggerProvider>(new TestProvider());
+ // tests GetLogger(name, version, schema)
+ const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"};
+ auto logger = tf->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url);
+ EXPECT_EQ(nullptr, logger);
+
+ // tests GetLogger(name, arguments)
+
+ std::array<nostd::string_view, 1> sv{"string"};
+ nostd::span<nostd::string_view> args{sv};
+ auto logger2 = tf->GetLogger("logger2", args, "opentelelemtry_library", "", schema_url);
+ EXPECT_EQ(nullptr, logger2);
+}
+#endif
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/metrics/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/BUILD
new file mode 100644
index 000000000..d15d7511f
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/BUILD
@@ -0,0 +1,31 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "noop_sync_instrument_test",
+ srcs = [
+ "noop_sync_instrument_test.cc",
+ ],
+ tags = [
+ "metrics",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "meter_provider_test",
+ srcs = [
+ "meter_provider_test.cc",
+ ],
+ tags = [
+ "metrics",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/metrics/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/CMakeLists.txt
new file mode 100644
index 000000000..89ce81fd0
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/CMakeLists.txt
@@ -0,0 +1,9 @@
+foreach(testname meter_provider_test noop_sync_instrument_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX metrics_new.
+ TEST_LIST ${testname})
+endforeach()
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/metrics/meter_provider_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/meter_provider_test.cc
new file mode 100644
index 000000000..161d852f0
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/meter_provider_test.cc
@@ -0,0 +1,38 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef ENABLE_METRICS_PREVIEW
+
+# include <gtest/gtest.h>
+# include "opentelemetry/metrics/noop.h"
+# include "opentelemetry/metrics/provider.h"
+# include "opentelemetry/nostd/shared_ptr.h"
+
+using opentelemetry::metrics::Meter;
+using opentelemetry::metrics::MeterProvider;
+using opentelemetry::metrics::NoopMeterProvider;
+using opentelemetry::metrics::Provider;
+
+TEST(Provider, GetMeterProviderDefault)
+{
+ auto tf = Provider::GetMeterProvider();
+ EXPECT_NE(nullptr, tf);
+}
+
+TEST(Provider, SetMeterProvider)
+{
+ auto tf = opentelemetry::nostd::shared_ptr<MeterProvider>(new NoopMeterProvider());
+ Provider::SetMeterProvider(tf);
+ ASSERT_EQ(tf, Provider::GetMeterProvider());
+}
+
+TEST(Provider, MultipleMeterProviders)
+{
+ auto tf = opentelemetry::nostd::shared_ptr<MeterProvider>(new NoopMeterProvider());
+ Provider::SetMeterProvider(tf);
+ auto tf2 = opentelemetry::nostd::shared_ptr<MeterProvider>(new NoopMeterProvider());
+ Provider::SetMeterProvider(tf2);
+
+ ASSERT_NE(Provider::GetMeterProvider(), tf);
+}
+#endif
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/metrics/noop_sync_instrument_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/noop_sync_instrument_test.cc
new file mode 100644
index 000000000..62be4f34a
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/noop_sync_instrument_test.cc
@@ -0,0 +1,50 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef ENABLE_METRICS_PREVIEW
+
+# include <gtest/gtest.h>
+# include <map>
+# include "opentelemetry/metrics/noop.h"
+
+TEST(Counter, Add)
+{
+ std::shared_ptr<opentelemetry::metrics::Counter<long>> counter{
+ new opentelemetry::metrics::NoopCounter<long>("test", "none", "unitless")};
+
+ std::map<std::string, std::string> labels = {{"k1", "v1"}};
+ EXPECT_NO_THROW(counter->Add(10l, labels));
+ EXPECT_NO_THROW(counter->Add(10l, labels, opentelemetry::context::Context{}));
+ EXPECT_NO_THROW(counter->Add(2l));
+ EXPECT_NO_THROW(counter->Add(2l, opentelemetry::context::Context{}));
+ EXPECT_NO_THROW(counter->Add(10l, {{"k1", "1"}, {"k2", 2}}));
+ EXPECT_NO_THROW(counter->Add(10l, {{"k1", "1"}, {"k2", 2}}, opentelemetry::context::Context{}));
+}
+
+TEST(histogram, Record)
+{
+ std::shared_ptr<opentelemetry::metrics::Histogram<long>> counter{
+ new opentelemetry::metrics::NoopHistogram<long>("test", "none", "unitless")};
+
+ std::map<std::string, std::string> labels = {{"k1", "v1"}};
+ EXPECT_NO_THROW(counter->Record(10l, labels, opentelemetry::context::Context{}));
+ EXPECT_NO_THROW(counter->Record(2l, opentelemetry::context::Context{}));
+ EXPECT_NO_THROW(
+ counter->Record(10l, {{"k1", "1"}, {"k2", 2}}, opentelemetry::context::Context{}));
+}
+
+TEST(UpDownCountr, Record)
+{
+ std::shared_ptr<opentelemetry::metrics::UpDownCounter<long>> counter{
+ new opentelemetry::metrics::NoopUpDownCounter<long>("test", "none", "unitless")};
+
+ std::map<std::string, std::string> labels = {{"k1", "v1"}};
+ EXPECT_NO_THROW(counter->Add(10l, labels));
+ EXPECT_NO_THROW(counter->Add(10l, labels, opentelemetry::context::Context{}));
+ EXPECT_NO_THROW(counter->Add(2l));
+ EXPECT_NO_THROW(counter->Add(2l, opentelemetry::context::Context{}));
+ EXPECT_NO_THROW(counter->Add(10l, {{"k1", "1"}, {"k2", 2}}));
+ EXPECT_NO_THROW(counter->Add(10l, {{"k1", "1"}, {"k2", 2}}, opentelemetry::context::Context{}));
+}
+
+#endif \ No newline at end of file
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/BUILD
new file mode 100644
index 000000000..75166c5de
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/BUILD
@@ -0,0 +1,104 @@
+cc_test(
+ name = "function_ref_test",
+ srcs = [
+ "function_ref_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "string_view_test",
+ srcs = [
+ "string_view_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "variant_test",
+ srcs = [
+ "variant_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "unique_ptr_test",
+ srcs = [
+ "unique_ptr_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "utility_test",
+ srcs = [
+ "utility_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "span_test",
+ srcs = [
+ "span_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "shared_ptr_test",
+ srcs = [
+ "shared_ptr_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/CMakeLists.txt
new file mode 100644
index 000000000..dd783bf2d
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/CMakeLists.txt
@@ -0,0 +1,19 @@
+include(GoogleTest)
+
+foreach(
+ testname
+ function_ref_test
+ string_view_test
+ unique_ptr_test
+ utility_test
+ span_test
+ shared_ptr_test
+ variant_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX nostd.
+ TEST_LIST ${testname})
+endforeach()
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/function_ref_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/function_ref_test.cc
new file mode 100644
index 000000000..1153360d2
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/function_ref_test.cc
@@ -0,0 +1,36 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/function_ref.h"
+
+#include <gtest/gtest.h>
+using namespace opentelemetry::nostd;
+
+int Call(function_ref<int()> f)
+{
+ return f();
+}
+
+int Return3()
+{
+ return 3;
+}
+
+TEST(FunctionRefTest, Call)
+{
+ int x = 9;
+
+ auto f = [&] { return x; };
+ EXPECT_EQ(Call(f), 9);
+
+ EXPECT_EQ(Call(Return3), 3);
+}
+
+TEST(FunctionRefTest, BoolConversion)
+{
+ auto f = [] { return 0; };
+ function_ref<int()> fref1{nullptr};
+ function_ref<int()> fref2{f};
+ EXPECT_TRUE(!static_cast<bool>(fref1));
+ EXPECT_TRUE(static_cast<bool>(fref2));
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/shared_ptr_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/shared_ptr_test.cc
new file mode 100644
index 000000000..6f3d43a77
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/shared_ptr_test.cc
@@ -0,0 +1,189 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/shared_ptr.h"
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+
+using opentelemetry::nostd::shared_ptr;
+
+class A
+{
+public:
+ explicit A(bool &destructed) noexcept : destructed_{destructed} { destructed_ = false; }
+
+ ~A() { destructed_ = true; }
+
+private:
+ bool &destructed_;
+};
+
+class B
+{
+public:
+ int f() const { return 123; }
+};
+
+class C
+{
+public:
+ virtual ~C() {}
+};
+
+class D : public C
+{
+public:
+ virtual ~D() {}
+};
+
+TEST(SharedPtrTest, DefaultConstruction)
+{
+ shared_ptr<int> ptr1;
+ EXPECT_EQ(ptr1.get(), nullptr);
+
+ shared_ptr<int> ptr2{nullptr};
+ EXPECT_EQ(ptr2.get(), nullptr);
+}
+
+TEST(SharedPtrTest, ExplicitConstruction)
+{
+ auto c = new C();
+ shared_ptr<C> ptr1{c};
+ EXPECT_EQ(ptr1.get(), c);
+
+ auto d = new D();
+ shared_ptr<C> ptr2{d};
+ EXPECT_EQ(ptr2.get(), d);
+}
+
+TEST(SharedPtrTest, MoveConstruction)
+{
+ auto value = new int{123};
+ shared_ptr<int> ptr1{value};
+ shared_ptr<int> ptr2{std::move(ptr1)};
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), value);
+}
+
+TEST(SharedPtrTest, MoveConstructionFromDifferentType)
+{
+ auto value = new int{123};
+ shared_ptr<int> ptr1{value};
+ shared_ptr<const int> ptr2{std::move(ptr1)};
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), value);
+}
+
+TEST(SharedPtrTest, MoveConstructionFromStdSharedPtr)
+{
+ auto value = new int{123};
+ std::shared_ptr<int> ptr1{value};
+ shared_ptr<int> ptr2{std::move(ptr1)};
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), value);
+}
+
+TEST(SharedPtrTest, Destruction)
+{
+ bool was_destructed;
+ shared_ptr<A>{new A{was_destructed}};
+ EXPECT_TRUE(was_destructed);
+}
+
+TEST(SharedPtrTest, Assignment)
+{
+ auto value = new int{123};
+ shared_ptr<int> ptr1;
+
+ ptr1 = shared_ptr<int>(value);
+ EXPECT_EQ(ptr1.get(), value);
+
+ ptr1 = nullptr;
+ EXPECT_EQ(ptr1.get(), nullptr);
+
+ auto value2 = new int{234};
+ const shared_ptr<int> ptr2 = shared_ptr<int>(value2);
+ ptr1 = ptr2;
+ EXPECT_EQ(ptr1.get(), value2);
+
+ auto value3 = new int{345};
+ std::shared_ptr<int> ptr3(value3);
+ ptr1 = ptr3;
+ EXPECT_EQ(ptr1.get(), value3);
+}
+
+TEST(SharedPtrTest, BoolConversionOpertor)
+{
+ auto value = new int{123};
+ shared_ptr<int> ptr1{value};
+
+ EXPECT_TRUE(ptr1);
+ EXPECT_FALSE(shared_ptr<int>{});
+}
+
+TEST(SharedPtrTest, PointerOperators)
+{
+ auto value = new int{123};
+ shared_ptr<int> ptr1{value};
+
+ EXPECT_EQ(&*ptr1, value);
+ EXPECT_EQ(
+ shared_ptr<B> { new B }->f(), 123);
+}
+
+TEST(SharedPtrTest, Swap)
+{
+ auto value1 = new int{123};
+ shared_ptr<int> ptr1{value1};
+
+ auto value2 = new int{456};
+ shared_ptr<int> ptr2{value2};
+ ptr1.swap(ptr2);
+
+ EXPECT_EQ(ptr1.get(), value2);
+ EXPECT_EQ(ptr2.get(), value1);
+}
+
+TEST(SharedPtrTest, Comparison)
+{
+ shared_ptr<int> ptr1{new int{123}};
+ shared_ptr<int> ptr2{new int{456}};
+ shared_ptr<int> ptr3{};
+
+ EXPECT_EQ(ptr1, ptr1);
+ EXPECT_NE(ptr1, ptr2);
+
+ EXPECT_NE(ptr1, nullptr);
+ EXPECT_NE(nullptr, ptr1);
+
+ EXPECT_EQ(ptr3, nullptr);
+ EXPECT_EQ(nullptr, ptr3);
+}
+
+static void SharedPtrTest_Sort(size_t size = 10)
+{
+ std::vector<shared_ptr<const int>> nums;
+
+ for (int i = static_cast<int>(size); i > 0; i--)
+ {
+ nums.push_back(shared_ptr<int>(new int(i)));
+ }
+
+ auto nums2 = nums;
+
+ std::sort(nums.begin(), nums.end(),
+ [](shared_ptr<const int> a, shared_ptr<const int> b) { return *a < *b; });
+
+ EXPECT_NE(nums, nums2);
+
+ std::reverse(nums2.begin(), nums2.end());
+
+ EXPECT_EQ(nums, nums2);
+}
+
+TEST(SharedPtrTest, Sort)
+{
+ SharedPtrTest_Sort();
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/span_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/span_test.cc
new file mode 100644
index 000000000..09d32ecfb
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/span_test.cc
@@ -0,0 +1,191 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/span.h"
+
+#include <cstdint>
+
+#include <algorithm>
+#include <array>
+#include <iterator>
+#include <list>
+#include <type_traits>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+using opentelemetry::nostd::span;
+
+TEST(SpanTest, DefaultConstruction)
+{
+ span<int> s1;
+ EXPECT_EQ(s1.data(), nullptr);
+ EXPECT_EQ(s1.size(), 0);
+ EXPECT_TRUE(s1.empty());
+
+ span<int, 0> s2;
+ EXPECT_EQ(s2.data(), nullptr);
+ EXPECT_EQ(s2.size(), 0);
+ EXPECT_TRUE(s2.empty());
+
+ EXPECT_FALSE((std::is_default_constructible<span<int, 1>>::value));
+}
+
+TEST(SpanTest, Assignment)
+{
+ std::array<int, 3> array1 = {1, 2, 3};
+ std::array<int, 3> array2 = {1, 2, 3};
+ span<int> s1{array1.data(), array1.size()};
+ span<int, 3> s2{array1.data(), array1.size()};
+
+ span<int> s3;
+ s3 = s1;
+ EXPECT_EQ(s3.data(), array1.data());
+ EXPECT_EQ(s3.size(), array1.size());
+
+ span<int, 3> s4{array2};
+ s4 = s2;
+ EXPECT_EQ(s4.data(), array1.data());
+ EXPECT_EQ(s4.size(), array1.size());
+}
+
+TEST(SpanTest, PointerCountConstruction)
+{
+ std::array<int, 3> array = {1, 2, 3};
+
+ span<int> s1{array.data(), array.size()};
+ EXPECT_EQ(s1.data(), array.data());
+ EXPECT_EQ(s1.size(), array.size());
+
+ span<int, 3> s2{array.data(), array.size()};
+ EXPECT_EQ(s2.data(), array.data());
+ EXPECT_EQ(s2.size(), array.size());
+
+#ifndef HAVE_CPP_STDLIB
+ /* This test is not supposed to fail with STL. Why is this invalid construct? */
+ EXPECT_DEATH((span<int, 2>{array.data(), array.size()}), ".*");
+#endif
+}
+
+TEST(SpanTest, RangeConstruction)
+{
+ int array[] = {1, 2, 3};
+
+ span<int> s1{std::begin(array), std::end(array)};
+ EXPECT_EQ(s1.data(), array);
+ EXPECT_EQ(s1.size(), 3);
+
+ span<int, 3> s2{std::begin(array), std::end(array)};
+ EXPECT_EQ(s2.data(), array);
+ EXPECT_EQ(s2.size(), 3);
+
+#ifndef HAVE_CPP_STDLIB
+ /* This test is not supposed to fail with STL. Why is this invalid construct? */
+ EXPECT_DEATH((span<int, 2>{std::begin(array), std::end(array)}), ".*");
+#endif
+}
+
+TEST(SpanTest, ArrayConstruction)
+{
+ int array1[] = {1, 2, 3};
+ std::array<int, 3> array2 = {1, 2, 3};
+
+ span<int> s1{array1};
+ EXPECT_EQ(s1.data(), array1);
+ EXPECT_EQ(s1.size(), 3);
+
+ span<int> s2{array2};
+ EXPECT_EQ(s2.data(), array2.data());
+ EXPECT_EQ(s2.size(), array2.size());
+
+ span<int, 3> s3{array1};
+ EXPECT_EQ(s3.data(), array1);
+ EXPECT_EQ(s3.size(), 3);
+
+ span<int, 3> s4{array2};
+ EXPECT_EQ(s4.data(), array2.data());
+ EXPECT_EQ(s4.size(), array2.size());
+
+ EXPECT_FALSE((std::is_constructible<span<int, 2>, int(&)[3]>::value));
+}
+
+TEST(SpanTest, ContainerConstruction)
+{
+ std::vector<int> v = {1, 2, 3};
+
+ span<int> s1{v};
+ EXPECT_EQ(s1.data(), v.data());
+ EXPECT_EQ(s1.size(), v.size());
+
+ span<int, 3> s2{v.data(), 3};
+
+ EXPECT_EQ(s2.data(), v.data());
+ EXPECT_EQ(s2.size(), v.size());
+
+#ifndef HAVE_CPP_STDLIB
+ /* This test is not supposed to fail with STL. Why is this invalid construct? */
+ EXPECT_DEATH((span<int, 2>{v.data(), 3}), ".*");
+#endif
+
+ EXPECT_FALSE((std::is_constructible<span<int>, std::vector<double>>::value));
+ EXPECT_FALSE((std::is_constructible<span<int>, std::list<int>>::value));
+}
+
+TEST(SpanTest, OtherSpanConstruction)
+{
+ std::array<int, 3> array = {1, 2, 3};
+ span<int> s1{array.data(), array.size()};
+ span<int, 3> s2{array.data(), array.size()};
+
+ span<int> s3{s1};
+ EXPECT_EQ(s3.data(), array.data());
+ EXPECT_EQ(s3.size(), array.size());
+
+ span<int> s4{s2};
+ EXPECT_EQ(s4.data(), array.data());
+ EXPECT_EQ(s4.size(), array.size());
+
+ span<const int> s5{s1};
+ EXPECT_EQ(s5.data(), array.data());
+ EXPECT_EQ(s5.size(), array.size());
+
+ EXPECT_FALSE((std::is_constructible<span<int>, span<const int>>::value));
+ EXPECT_FALSE((std::is_constructible<span<int>, span<double>>::value));
+
+ span<int, 3> s6{s2};
+ EXPECT_EQ(s6.data(), array.data());
+ EXPECT_EQ(s6.size(), array.size());
+
+ span<const int, 3> s7{s2};
+ EXPECT_EQ(s7.data(), array.data());
+ EXPECT_EQ(s7.size(), array.size());
+
+ EXPECT_FALSE((std::is_constructible<span<int, 3>, span<int, 4>>::value));
+ EXPECT_FALSE((std::is_constructible<span<int, 3>, span<double, 3>>::value));
+}
+
+TEST(SpanTest, BracketOperator)
+{
+ std::array<int, 2> array = {1, 2};
+
+ span<int> s1{array.data(), array.size()};
+ EXPECT_EQ(s1[0], 1);
+ EXPECT_EQ(s1[1], 2);
+
+ span<int, 2> s2{array.data(), array.size()};
+ EXPECT_EQ(s2[0], 1);
+ EXPECT_EQ(s2[1], 2);
+}
+
+TEST(SpanTest, Iteration)
+{
+ std::array<int, 3> array = {1, 2, 3};
+
+ span<int> s1{array.data(), array.size()};
+ EXPECT_EQ(std::distance(s1.begin(), s1.end()), array.size());
+ EXPECT_TRUE(std::equal(s1.begin(), s1.end(), array.begin()));
+
+ span<int, 3> s2{array.data(), array.size()};
+ EXPECT_EQ(std::distance(s2.begin(), s2.end()), array.size());
+ EXPECT_TRUE(std::equal(s2.begin(), s2.end(), array.begin()));
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/string_view_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/string_view_test.cc
new file mode 100644
index 000000000..fc580debc
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/string_view_test.cc
@@ -0,0 +1,125 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/string_view.h"
+
+#include <gtest/gtest.h>
+#include <cstring>
+#include <map>
+
+using opentelemetry::nostd::string_view;
+
+TEST(StringViewTest, DefaultConstruction)
+{
+ string_view ref;
+ EXPECT_EQ(ref.data(), nullptr);
+ EXPECT_EQ(ref.length(), 0);
+}
+
+TEST(StringViewTest, CStringInitialization)
+{
+ const char *val = "hello world";
+
+ string_view ref(val);
+
+ EXPECT_EQ(ref.data(), val);
+ EXPECT_EQ(ref.length(), std::strlen(val));
+}
+
+TEST(StringViewTest, StdStringInitialization)
+{
+ const std::string val = "hello world";
+
+ string_view ref(val);
+
+ EXPECT_EQ(ref.data(), val.data());
+ EXPECT_EQ(ref.length(), val.size());
+}
+
+TEST(StringViewTest, Copy)
+{
+ const std::string val = "hello world";
+
+ string_view ref(val);
+ string_view cpy(ref);
+
+ EXPECT_EQ(cpy.data(), val);
+ EXPECT_EQ(cpy.length(), val.length());
+ EXPECT_EQ(cpy, val);
+}
+
+TEST(StringViewTest, Accessor)
+{
+ string_view s = "abc123";
+ EXPECT_EQ(s.data(), &s[0]);
+ EXPECT_EQ(s.data() + 1, &s[1]);
+}
+
+TEST(StringViewTest, ExplicitStdStringConversion)
+{
+ std::string s = static_cast<std::string>(string_view{"abc"});
+ EXPECT_EQ(s, "abc");
+}
+
+TEST(StringViewTest, SubstrPortion)
+{
+ string_view s = "abc123";
+ EXPECT_EQ("123", s.substr(3));
+ EXPECT_EQ("12", s.substr(3, 2));
+}
+
+TEST(StringViewTest, SubstrOutOfRange)
+{
+ string_view s = "abc123";
+#if __EXCEPTIONS || defined(HAVE_CPP_STDLIB)
+ EXPECT_THROW(s.substr(10), std::out_of_range);
+#else
+ EXPECT_DEATH({ s.substr(10); }, "");
+#endif
+}
+
+TEST(StringViewTest, FindSingleCharacter)
+{
+ string_view s = "abc";
+
+ // starting from 0-th position (default)
+ EXPECT_EQ(s.find('a'), 0);
+ EXPECT_EQ(s.find('b'), 1);
+ EXPECT_EQ(s.find('c'), 2);
+ EXPECT_EQ(s.find('d'), -1); // FIXME: string_view:npos - problem with linker
+
+ // starting from given index
+ EXPECT_EQ(s.find('a', 1), -1);
+ EXPECT_EQ(s.find('b', 1), 1);
+
+ // out of index
+ EXPECT_EQ(s.find('a', 10), -1);
+}
+
+TEST(StringViewTest, Compare)
+{
+ string_view s1 = "aaa";
+ string_view s2 = "bbb";
+ string_view s3 = "aaa";
+
+ // Equals
+ EXPECT_EQ(s1, s3);
+ EXPECT_EQ(s1, s1);
+
+ // Less then
+ EXPECT_LT(s1, s2);
+
+ // Greater then
+ EXPECT_GT(s2, s1);
+}
+
+TEST(StringViewTest, MapKeyOrdering)
+{
+ std::map<string_view, size_t> m = {{"bbb", 2}, {"aaa", 1}, {"ccc", 3}};
+ size_t i = 1;
+ for (const auto &kv : m)
+ {
+ EXPECT_EQ(kv.second, i);
+ i++;
+ }
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/unique_ptr_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/unique_ptr_test.cc
new file mode 100644
index 000000000..1d2e6c062
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/unique_ptr_test.cc
@@ -0,0 +1,169 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/unique_ptr.h"
+
+#include <gtest/gtest.h>
+
+using opentelemetry::nostd::unique_ptr;
+
+class A
+{
+public:
+ explicit A(bool &destructed) noexcept : destructed_{destructed} { destructed_ = false; }
+
+ ~A() { destructed_ = true; }
+
+private:
+ bool &destructed_;
+};
+
+class B
+{
+public:
+ int f() const { return 123; }
+};
+
+TEST(UniquePtrTest, DefaultConstruction)
+{
+ unique_ptr<int> ptr1;
+ EXPECT_EQ(ptr1.get(), nullptr);
+
+ unique_ptr<int> ptr2{nullptr};
+ EXPECT_EQ(ptr2.get(), nullptr);
+}
+
+TEST(UniquePtrTest, ExplicitConstruction)
+{
+ auto value = new int{123};
+ unique_ptr<int> ptr1{value};
+ EXPECT_EQ(ptr1.get(), value);
+
+ auto array = new int[5];
+ unique_ptr<int[]> ptr2{array};
+ EXPECT_EQ(ptr2.get(), array);
+}
+
+TEST(UniquePtrTest, MoveConstruction)
+{
+ auto value = new int{123};
+ unique_ptr<int> ptr1{value};
+ unique_ptr<int> ptr2{std::move(ptr1)};
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), value);
+}
+
+TEST(UniquePtrTest, MoveConstructionFromDifferentType)
+{
+ auto value = new int{123};
+ unique_ptr<int> ptr1{value};
+ unique_ptr<const int> ptr2{std::move(ptr1)};
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), value);
+}
+
+TEST(UniquePtrTest, MoveConstructionFromStdUniquePtr)
+{
+ auto value = new int{123};
+ std::unique_ptr<int> ptr1{value};
+ unique_ptr<int> ptr2{std::move(ptr1)};
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), value);
+}
+
+TEST(UniquePtrTest, Destruction)
+{
+ bool was_destructed;
+ unique_ptr<A>{new A{was_destructed}};
+ EXPECT_TRUE(was_destructed);
+}
+
+TEST(UniquePtrTest, StdUniquePtrConversionOperator)
+{
+ auto value = new int{123};
+ unique_ptr<int> ptr1{value};
+ std::unique_ptr<int> ptr2{std::move(ptr1)};
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), value);
+
+ value = new int{456};
+ ptr1 = unique_ptr<int>{value};
+ ptr2 = std::move(ptr1);
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), value);
+
+ ptr2 = nullptr;
+ EXPECT_EQ(ptr2.get(), nullptr);
+
+ EXPECT_TRUE((std::is_assignable<std::unique_ptr<int>, unique_ptr<int> &&>::value));
+ EXPECT_FALSE((std::is_assignable<std::unique_ptr<int>, unique_ptr<int> &>::value));
+}
+
+TEST(UniquePtrTest, BoolConversionOpertor)
+{
+ auto value = new int{123};
+ unique_ptr<int> ptr1{value};
+
+ EXPECT_TRUE(ptr1);
+ EXPECT_FALSE(unique_ptr<int>{});
+}
+
+TEST(UniquePtrTest, PointerOperators)
+{
+ auto value = new int{123};
+ unique_ptr<int> ptr1{value};
+
+ EXPECT_EQ(&*ptr1, value);
+ EXPECT_EQ(
+ unique_ptr<B> { new B }->f(), 123);
+}
+
+TEST(UniquePtrTest, Reset)
+{
+ bool was_destructed1;
+ unique_ptr<A> ptr{new A{was_destructed1}};
+ bool was_destructed2;
+ ptr.reset(new A{was_destructed2});
+ EXPECT_TRUE(was_destructed1);
+ EXPECT_FALSE(was_destructed2);
+ ptr.reset();
+ EXPECT_TRUE(was_destructed2);
+}
+
+TEST(UniquePtrTest, Release)
+{
+ auto value = new int{123};
+ unique_ptr<int> ptr{value};
+ EXPECT_EQ(ptr.release(), value);
+ EXPECT_EQ(ptr.get(), nullptr);
+ delete value;
+}
+
+TEST(UniquePtrTest, Swap)
+{
+ auto value1 = new int{123};
+ unique_ptr<int> ptr1{value1};
+
+ auto value2 = new int{456};
+ unique_ptr<int> ptr2{value2};
+ ptr1.swap(ptr2);
+
+ EXPECT_EQ(ptr1.get(), value2);
+ EXPECT_EQ(ptr2.get(), value1);
+}
+
+TEST(UniquePtrTest, Comparison)
+{
+ unique_ptr<int> ptr1{new int{123}};
+ unique_ptr<int> ptr2{new int{456}};
+ unique_ptr<int> ptr3{};
+
+ EXPECT_EQ(ptr1, ptr1);
+ EXPECT_NE(ptr1, ptr2);
+
+ EXPECT_NE(ptr1, nullptr);
+ EXPECT_NE(nullptr, ptr1);
+
+ EXPECT_EQ(ptr3, nullptr);
+ EXPECT_EQ(nullptr, ptr3);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/utility_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/utility_test.cc
new file mode 100644
index 000000000..821b2a70a
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/utility_test.cc
@@ -0,0 +1,56 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/utility.h"
+
+#include <tuple>
+#include <type_traits>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+namespace nostd = opentelemetry::nostd;
+
+template <class T>
+auto IsDataCallable(const T &t) -> decltype(nostd::data(t), std::true_type{});
+
+std::false_type IsDataCallable(...);
+
+template <class T>
+auto IsSizeCallable(const T &t) -> decltype(nostd::size(t), std::true_type{});
+
+std::false_type IsSizeCallable(...);
+
+TEST(UtilityTest, Data)
+{
+ std::vector<int> v = {1, 2, 3};
+ int array[3] = {1, 2, 3};
+ std::initializer_list<int> list{1, 2, 3};
+ int x = 0;
+ std::ignore = x;
+
+ EXPECT_EQ(nostd::data(v), v.data());
+ EXPECT_EQ(nostd::data(array), array);
+ EXPECT_EQ(nostd::data(list), list.begin());
+ EXPECT_FALSE(decltype(IsDataCallable(x)){});
+}
+
+TEST(UtilityTest, Size)
+{
+ std::vector<int> v = {1, 2, 3};
+ int array[3] = {1, 2, 3};
+ int x = 0;
+ std::ignore = x;
+
+ EXPECT_EQ(nostd::size(v), v.size());
+ EXPECT_EQ(nostd::size(array), 3);
+
+ EXPECT_FALSE(decltype(IsSizeCallable(x)){});
+}
+
+TEST(UtilityTest, MakeIndexSequence)
+{
+ EXPECT_TRUE((std::is_same<nostd::make_index_sequence<0>, nostd::index_sequence<>>::value));
+ EXPECT_TRUE((std::is_same<nostd::make_index_sequence<1>, nostd::index_sequence<0>>::value));
+ EXPECT_TRUE((std::is_same<nostd::make_index_sequence<2>, nostd::index_sequence<0, 1>>::value));
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/variant_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/variant_test.cc
new file mode 100644
index 000000000..cea5c4ee7
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/variant_test.cc
@@ -0,0 +1,119 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/variant.h"
+
+#include <string>
+#include <type_traits>
+
+#include <gtest/gtest.h>
+
+namespace nostd = opentelemetry::nostd;
+
+class DestroyCounter
+{
+public:
+ explicit DestroyCounter(int *count) : count_{count} {}
+ ~DestroyCounter() { ++*count_; }
+
+private:
+ int *count_;
+};
+
+TEST(VariantSizeTest, GetVariantSize)
+{
+ EXPECT_EQ(nostd::variant_size<nostd::variant<>>::value, 0);
+ EXPECT_EQ(nostd::variant_size<nostd::variant<int>>::value, 1);
+ EXPECT_EQ((nostd::variant_size<nostd::variant<int, double>>::value), 2);
+}
+
+#if 0 // Disable this test for now. It does not compile with Visual Studio 2015.
+TEST(VariantAlternativeTest, GetVariantSize)
+{
+ EXPECT_TRUE((std::is_same<nostd::variant_alternative_t<0, nostd::variant<int>>, int>::value));
+ EXPECT_TRUE(
+ (std::is_same<nostd::variant_alternative_t<1, nostd::variant<int, double>>, double>::value));
+ EXPECT_TRUE((std::is_same<nostd::variant_alternative_t<1, const nostd::variant<int, double>>,
+ const double>::value));
+}
+#endif
+
+TEST(VariantTest, Get)
+{
+ nostd::variant<int, float> v, w;
+ v = 12;
+ EXPECT_EQ(nostd::get<int>(v), 12);
+ EXPECT_EQ(nostd::get<0>(v), 12);
+ w = v;
+ EXPECT_EQ(nostd::get<int>(w), 12);
+ EXPECT_EQ(*nostd::get_if<int>(&v), 12);
+ EXPECT_EQ(nostd::get_if<float>(&v), nullptr);
+#if __EXCEPTIONS
+ EXPECT_THROW(nostd::get<float>(w), nostd::bad_variant_access);
+#else
+ EXPECT_DEATH({ nostd::get<float>(w); }, "");
+#endif
+}
+
+TEST(VariantTest, Comparison)
+{
+ nostd::variant<int, float> v, w;
+ EXPECT_TRUE(v == w);
+ EXPECT_FALSE(v != w);
+ v = 3.0f;
+ EXPECT_TRUE(v != w);
+ EXPECT_FALSE(v == w);
+ v = 2;
+ w = 3;
+ EXPECT_TRUE(v != w);
+ EXPECT_FALSE(v == w);
+ EXPECT_TRUE(v < w);
+ EXPECT_FALSE(v > w);
+}
+
+TEST(VariantTest, Visit)
+{
+ nostd::variant<int, float> v;
+ struct
+ {
+ int operator()(int) { return 0; }
+ int operator()(float) { return 1; }
+ } a;
+ EXPECT_EQ(nostd::visit(a, v), 0);
+ v = 2.0f;
+ EXPECT_EQ(nostd::visit(a, v), 1);
+}
+
+TEST(VariantTest, Destructor)
+{
+ nostd::variant<int, DestroyCounter> v;
+ int destroy_count = 0;
+ v = DestroyCounter{&destroy_count};
+ destroy_count = 0;
+ v = 1;
+ EXPECT_EQ(destroy_count, 1);
+ {
+ nostd::variant<int, DestroyCounter> w;
+ w = DestroyCounter{&destroy_count};
+ destroy_count = 0;
+ }
+ EXPECT_EQ(destroy_count, 1);
+}
+
+TEST(VariantTest, Conversion)
+{
+ nostd::variant<std::string> x("abc");
+ x = "def";
+ EXPECT_EQ(nostd::get<std::string>(x), "def");
+
+ nostd::variant<std::string, void const *> y("abc");
+ EXPECT_TRUE(nostd::holds_alternative<void const *>(y));
+ y = std::string{"xyz"};
+ EXPECT_TRUE(nostd::holds_alternative<std::string>(y));
+}
+
+TEST(VariantTest, Construction)
+{
+ nostd::variant<bool, const char *, std::string> v{"abc"};
+ EXPECT_EQ(v.index(), 1);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/plugin/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/BUILD
new file mode 100644
index 000000000..98e3679b3
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/BUILD
@@ -0,0 +1,17 @@
+cc_test(
+ name = "dynamic_load_test",
+ srcs = [
+ "dynamic_load_test.cc",
+ ],
+ linkopts = [
+ "-ldl",
+ ],
+ tags = [
+ "api",
+ "test",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/plugin/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/CMakeLists.txt
new file mode 100644
index 000000000..6bdcbf9c3
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/CMakeLists.txt
@@ -0,0 +1,10 @@
+include(GoogleTest)
+
+add_executable(dynamic_load_test dynamic_load_test.cc)
+target_link_libraries(dynamic_load_test ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+target_link_libraries(dynamic_load_test ${CMAKE_DL_LIBS})
+gtest_add_tests(
+ TARGET dynamic_load_test
+ TEST_PREFIX plugin.
+ TEST_LIST dynamic_load_test)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/plugin/dynamic_load_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/dynamic_load_test.cc
new file mode 100644
index 000000000..4fdc79eee
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/dynamic_load_test.cc
@@ -0,0 +1,14 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/plugin/dynamic_load.h"
+
+#include <gtest/gtest.h>
+
+TEST(LoadFactoryTest, FailureTest)
+{
+ std::string error_message;
+ auto factory = opentelemetry::plugin::LoadFactory("no-such-plugin", error_message);
+ EXPECT_EQ(factory, nullptr);
+ EXPECT_FALSE(error_message.empty());
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/trace/BUILD
new file mode 100644
index 000000000..a9b5b0170
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/BUILD
@@ -0,0 +1,199 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "default_span_test",
+ srcs = [
+ "default_span_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "noop_test",
+ srcs = [
+ "noop_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "key_value_iterable_view_test",
+ srcs = [
+ "key_value_iterable_view_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+otel_cc_benchmark(
+ name = "span_id_benchmark",
+ srcs = ["span_id_benchmark.cc"],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = ["//api"],
+)
+
+otel_cc_benchmark(
+ name = "span_benchmark",
+ srcs = ["span_benchmark.cc"],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = ["//api"],
+)
+
+cc_test(
+ name = "provider_test",
+ srcs = [
+ "provider_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "span_id_test",
+ srcs = [
+ "span_id_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "trace_flags_test",
+ srcs = [
+ "trace_flags_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "trace_id_test",
+ srcs = [
+ "trace_id_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "span_context_test",
+ srcs = [
+ "span_context_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "trace_state_test",
+ srcs = [
+ "trace_state_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "scope_test",
+ srcs = [
+ "scope_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "tracer_test",
+ srcs = [
+ "tracer_test.cc",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/trace/CMakeLists.txt
new file mode 100644
index 000000000..09d2c12d8
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/CMakeLists.txt
@@ -0,0 +1,29 @@
+add_subdirectory(propagation)
+
+foreach(
+ testname
+ key_value_iterable_view_test
+ provider_test
+ span_id_test
+ trace_id_test
+ trace_flags_test
+ span_context_test
+ scope_test
+ noop_test
+ trace_state_test
+ tracer_test)
+ add_executable(api_${testname} "${testname}.cc")
+ target_link_libraries(api_${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET api_${testname}
+ TEST_PREFIX trace.
+ TEST_LIST api_${testname})
+endforeach()
+
+add_executable(span_id_benchmark span_id_benchmark.cc)
+target_link_libraries(span_id_benchmark benchmark::benchmark
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+add_executable(span_benchmark span_benchmark.cc)
+target_link_libraries(span_benchmark benchmark::benchmark
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/default_span_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/default_span_test.cc
new file mode 100644
index 000000000..377a0a858
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/default_span_test.cc
@@ -0,0 +1,24 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/default_span.h"
+#include "opentelemetry/trace/span_context.h"
+
+#include <cstring>
+#include <string>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using opentelemetry::trace::DefaultSpan;
+using opentelemetry::trace::SpanContext;
+
+TEST(DefaultSpanTest, GetContext)
+{
+ SpanContext span_context = SpanContext(false, false);
+ DefaultSpan sp = DefaultSpan(span_context);
+ EXPECT_EQ(span_context, sp.GetContext());
+}
+} // namespace
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/key_value_iterable_view_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/key_value_iterable_view_test.cc
new file mode 100644
index 000000000..989856b42
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/key_value_iterable_view_test.cc
@@ -0,0 +1,68 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/common/key_value_iterable_view.h"
+
+#include <gtest/gtest.h>
+#include <map>
+#include "opentelemetry/nostd/type_traits.h"
+
+using namespace opentelemetry;
+
+static int TakeKeyValues(const common::KeyValueIterable &iterable)
+{
+ std::map<std::string, common::AttributeValue> result;
+ int count = 0;
+ iterable.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept {
+ ++count;
+ return true;
+ });
+ return count;
+}
+
+template <class T, nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr>
+static int TakeKeyValues(const T &iterable)
+{
+ return TakeKeyValues(common::KeyValueIterableView<T>{iterable});
+}
+
+TEST(KeyValueIterableViewTest, is_key_value_iterable)
+{
+ using M1 = std::map<std::string, std::string>;
+ EXPECT_TRUE(bool{common::detail::is_key_value_iterable<M1>::value});
+
+ using M2 = std::map<std::string, int>;
+ EXPECT_TRUE(bool{common::detail::is_key_value_iterable<M2>::value});
+
+ using M3 = std::map<std::string, common::AttributeValue>;
+ EXPECT_TRUE(bool{common::detail::is_key_value_iterable<M3>::value});
+
+ struct A
+ {};
+ using M4 = std::map<std::string, A>;
+ EXPECT_FALSE(bool{common::detail::is_key_value_iterable<M4>::value});
+}
+
+TEST(KeyValueIterableViewTest, ForEachKeyValue)
+{
+ std::map<std::string, std::string> m1 = {{"abc", "123"}, {"xyz", "456"}};
+ EXPECT_EQ(TakeKeyValues(m1), 2);
+
+ std::vector<std::pair<std::string, int>> v1 = {{"abc", 123}, {"xyz", 456}};
+ EXPECT_EQ(TakeKeyValues(v1), 2);
+}
+
+TEST(KeyValueIterableViewTest, ForEachKeyValueWithExit)
+{
+ using M = std::map<std::string, std::string>;
+ M m1 = {{"abc", "123"}, {"xyz", "456"}};
+ common::KeyValueIterableView<M> iterable{m1};
+ int count = 0;
+ auto exit = iterable.ForEachKeyValue(
+ [&count](nostd::string_view /*key*/, common::AttributeValue /*value*/) noexcept {
+ ++count;
+ return false;
+ });
+ EXPECT_EQ(count, 1);
+ EXPECT_FALSE(exit);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/noop_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/noop_test.cc
new file mode 100644
index 000000000..130496faf
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/noop_test.cc
@@ -0,0 +1,81 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/noop.h"
+#include "opentelemetry/common/timestamp.h"
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <gtest/gtest.h>
+
+namespace trace_api = opentelemetry::trace;
+namespace nonstd = opentelemetry::nostd;
+namespace common = opentelemetry::common;
+
+TEST(NoopTest, UseNoopTracers)
+{
+ std::shared_ptr<trace_api::Tracer> tracer{new trace_api::NoopTracer{}};
+ auto s1 = tracer->StartSpan("abc");
+
+ std::map<std::string, std::string> attributes1;
+ s1->AddEvent("abc", attributes1);
+
+ std::vector<std::pair<std::string, int>> attributes2;
+ s1->AddEvent("abc", attributes2);
+
+ s1->AddEvent("abc", {{"a", 1}, {"b", "2"}, {"c", 3.0}});
+
+ std::vector<std::pair<std::string, std::vector<int>>> attributes3;
+ s1->AddEvent("abc", attributes3);
+
+ s1->SetAttribute("abc", 4);
+
+ s1->AddEvent("abc"); // add Empty
+
+ EXPECT_EQ(s1->IsRecording(), false);
+
+ s1->SetStatus(trace_api::StatusCode::kUnset, "span unset");
+
+ s1->UpdateName("test_name");
+
+ common::SystemTimestamp t1;
+ s1->AddEvent("test_time_stamp", t1);
+
+ s1->GetContext();
+}
+
+TEST(NoopTest, StartSpan)
+{
+ std::shared_ptr<trace_api::Tracer> tracer{new trace_api::NoopTracer{}};
+
+ std::map<std::string, std::string> attrs = {{"a", "3"}};
+ std::vector<std::pair<trace_api::SpanContext, std::map<std::string, std::string>>> links = {
+ {trace_api::SpanContext(false, false), attrs}};
+ auto s1 = tracer->StartSpan("abc", attrs, links);
+
+ auto s2 =
+ tracer->StartSpan("efg", {{"a", 3}}, {{trace_api::SpanContext(false, false), {{"b", 4}}}});
+}
+
+TEST(NoopTest, CreateSpanValidSpanContext)
+{
+ // Create valid spancontext for NoopSpan
+
+ constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+ auto trace_id = trace_api::TraceId{buf_trace};
+ auto span_id = trace_api::SpanId{buf_span};
+ auto span_context = nonstd::unique_ptr<trace_api::SpanContext>(
+ new trace_api::SpanContext{trace_id, span_id, trace_api::TraceFlags{true}, false});
+ std::shared_ptr<trace_api::Tracer> tracer{new trace_api::NoopTracer{}};
+ auto s1 =
+ nonstd::shared_ptr<trace_api::Span>(new trace_api::NoopSpan(tracer, std::move(span_context)));
+ auto stored_span_context = s1->GetContext();
+ EXPECT_EQ(stored_span_context.span_id(), span_id);
+ EXPECT_EQ(stored_span_context.trace_id(), trace_id);
+
+ s1->AddEvent("even1"); // noop
+ s1->End(); // noop
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/BUILD
new file mode 100644
index 000000000..b21ba6bca
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/BUILD
@@ -0,0 +1,52 @@
+load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")
+
+cc_test(
+ name = "http_text_format_test",
+ srcs = [
+ "http_text_format_test.cc",
+ "util.h",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "b3_propagation_test",
+ srcs = [
+ "b3_propagation_test.cc",
+ "util.h",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "jaeger_propagation_test",
+ srcs = [
+ "jaeger_propagation_test.cc",
+ "util.h",
+ ],
+ tags = [
+ "api",
+ "test",
+ "trace",
+ ],
+ deps = [
+ "//api",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/CMakeLists.txt
new file mode 100644
index 000000000..da60712c6
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/CMakeLists.txt
@@ -0,0 +1,10 @@
+foreach(testname http_text_format_test b3_propagation_test
+ jaeger_propagation_test)
+ add_executable(${testname} "${testname}.cc")
+ target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
+ gtest_add_tests(
+ TARGET ${testname}
+ TEST_PREFIX trace.
+ TEST_LIST ${testname})
+endforeach()
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/b3_propagation_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/b3_propagation_test.cc
new file mode 100644
index 000000000..2538b5be2
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/b3_propagation_test.cc
@@ -0,0 +1,189 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/context/runtime_context.h"
+#include "opentelemetry/trace/propagation/b3_propagator.h"
+#include "opentelemetry/trace/scope.h"
+#include "util.h"
+
+#include <map>
+
+#include <gtest/gtest.h>
+
+using namespace opentelemetry;
+
+class TextMapCarrierTest : public context::propagation::TextMapCarrier
+{
+public:
+ virtual nostd::string_view Get(nostd::string_view key) const noexcept override
+ {
+ auto it = headers_.find(std::string(key));
+ if (it != headers_.end())
+ {
+ return nostd::string_view(it->second);
+ }
+ return "";
+ }
+ virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
+ {
+ headers_[std::string(key)] = std::string(value);
+ }
+
+ std::map<std::string, std::string> headers_;
+};
+
+using MapB3Context = trace::propagation::B3Propagator;
+
+static MapB3Context format = MapB3Context();
+
+using MapB3ContextMultiHeader = trace::propagation::B3PropagatorMultiHeader;
+
+static MapB3ContextMultiHeader formatMultiHeader = MapB3ContextMultiHeader();
+
+TEST(B3PropagationTest, TraceFlagsBufferGeneration)
+{
+ EXPECT_EQ(MapB3Context::TraceFlagsFromHex("0"), trace::TraceFlags());
+ EXPECT_EQ(MapB3Context::TraceFlagsFromHex("1"), trace::TraceFlags(trace::TraceFlags::kIsSampled));
+}
+
+TEST(B3PropagationTest, PropagateInvalidContext)
+{
+ // Do not propagate invalid trace context.
+ TextMapCarrierTest carrier;
+ context::Context ctx{
+ "current-span",
+ nostd::shared_ptr<trace::Span>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
+ format.Inject(carrier, ctx);
+ EXPECT_TRUE(carrier.headers_.count("b3") == 0);
+}
+
+TEST(B3PropagationTest, ExtractInvalidContext)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"b3", "00000000000000000000000000000000-0000000000000000-0"}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+ auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
+ auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
+ EXPECT_EQ(span->GetContext().IsRemote(), false);
+}
+
+TEST(B3PropagationTest, DoNotExtractWithInvalidHex)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"b3", "0000000zzz0000000000000000000000-0000000zzz000000-1"}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+ auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
+ auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
+ EXPECT_EQ(span->GetContext().IsRemote(), false);
+}
+
+TEST(B3PropagationTest, SetRemoteSpan)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {
+ {"b3", "80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90"}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
+ EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
+
+ auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
+
+ EXPECT_EQ(Hex(span->GetContext().trace_id()), "80f198ee56343ba864fe8b2a57d3eff7");
+ EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
+ EXPECT_EQ(span->GetContext().IsSampled(), true);
+ EXPECT_EQ(span->GetContext().IsRemote(), true);
+}
+
+TEST(B3PropagationTest, SetRemoteSpan_TraceIdShort)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"b3", "80f198ee56343ba8-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90"}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
+ EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
+
+ auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
+
+ EXPECT_EQ(Hex(span->GetContext().trace_id()), "000000000000000080f198ee56343ba8");
+ EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
+ EXPECT_EQ(span->GetContext().IsSampled(), true);
+ EXPECT_EQ(span->GetContext().IsRemote(), true);
+}
+
+TEST(B3PropagationTest, SetRemoteSpan_SingleHeaderNoFlags)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"b3", "80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1"}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
+ EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
+
+ auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
+
+ EXPECT_EQ(Hex(span->GetContext().trace_id()), "80f198ee56343ba864fe8b2a57d3eff7");
+ EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
+ EXPECT_EQ(span->GetContext().IsSampled(), false);
+ EXPECT_EQ(span->GetContext().IsRemote(), true);
+}
+
+TEST(B3PropagationTest, SetRemoteSpanMultiHeader)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"X-B3-TraceId", "80f198ee56343ba864fe8b2a57d3eff7"},
+ {"X-B3-SpanId", "e457b5a2e4d86bd1"},
+ {"X-B3-Sampled", "1"}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
+ EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
+
+ auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
+
+ EXPECT_EQ(Hex(span->GetContext().trace_id()), "80f198ee56343ba864fe8b2a57d3eff7");
+ EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
+ EXPECT_EQ(span->GetContext().IsSampled(), true);
+ EXPECT_EQ(span->GetContext().IsRemote(), true);
+}
+
+TEST(B3PropagationTest, GetCurrentSpan)
+{
+ TextMapCarrierTest carrier;
+ constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+ trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span},
+ trace::TraceFlags{true}, false};
+ nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}};
+
+ // Set `sp` as the currently active span, which must be used by `Inject`.
+ trace::Scope scoped_span{sp};
+
+ format.Inject(carrier, context::RuntimeContext::GetCurrent());
+ EXPECT_EQ(carrier.headers_["b3"], "0102030405060708090a0b0c0d0e0f10-0102030405060708-1");
+}
+
+TEST(B3PropagationTest, GetCurrentSpanMultiHeader)
+{
+ TextMapCarrierTest carrier;
+ constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+ trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span},
+ trace::TraceFlags{true}, false};
+ nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}};
+
+ // Set `sp` as the currently active span, which must be used by `Inject`.
+ trace::Scope scoped_span{sp};
+
+ formatMultiHeader.Inject(carrier, context::RuntimeContext::GetCurrent());
+ EXPECT_EQ(carrier.headers_["X-B3-TraceId"], "0102030405060708090a0b0c0d0e0f10");
+ EXPECT_EQ(carrier.headers_["X-B3-SpanId"], "0102030405060708");
+ EXPECT_EQ(carrier.headers_["X-B3-Sampled"], "1");
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/http_text_format_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/http_text_format_test.cc
new file mode 100644
index 000000000..8fa0e44ed
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/http_text_format_test.cc
@@ -0,0 +1,211 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/context/propagation/global_propagator.h"
+#include "opentelemetry/context/runtime_context.h"
+#include "opentelemetry/trace/context.h"
+#include "opentelemetry/trace/propagation/http_trace_context.h"
+#include "opentelemetry/trace/scope.h"
+#include "util.h"
+
+#include <map>
+#include <unordered_map>
+
+#include <gtest/gtest.h>
+
+using namespace opentelemetry;
+
+class TextMapCarrierTest : public context::propagation::TextMapCarrier
+{
+public:
+ virtual nostd::string_view Get(nostd::string_view key) const noexcept override
+ {
+ auto it = headers_.find(std::string(key));
+ if (it != headers_.end())
+ {
+ return nostd::string_view(it->second);
+ }
+ return "";
+ }
+ virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
+ {
+ headers_[std::string(key)] = std::string(value);
+ }
+
+ std::map<std::string, std::string> headers_;
+};
+
+using MapHttpTraceContext = trace::propagation::HttpTraceContext;
+
+static MapHttpTraceContext format = MapHttpTraceContext();
+
+TEST(TextMapPropagatorTest, TraceFlagsBufferGeneration)
+{
+ EXPECT_EQ(MapHttpTraceContext::TraceFlagsFromHex("00"), trace::TraceFlags());
+}
+
+TEST(TextMapPropagatorTest, NoSendEmptyTraceState)
+{
+ // If the trace state is empty, do not set the header.
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"}};
+ context::Context ctx1 = context::Context{
+ "current-span",
+ nostd::shared_ptr<trace::Span>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+ TextMapCarrierTest carrier2;
+ format.Inject(carrier2, ctx2);
+ EXPECT_TRUE(carrier2.headers_.count("traceparent") > 0);
+ EXPECT_FALSE(carrier2.headers_.count("tracestate") > 0);
+}
+
+TEST(TextMapPropagatorTest, PropogateTraceState)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"},
+ {"tracestate", "congo=t61rcWkgMzE"}};
+ context::Context ctx1 = context::Context{
+ "current-span",
+ nostd::shared_ptr<trace::Span>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ TextMapCarrierTest carrier2;
+ format.Inject(carrier2, ctx2);
+
+ EXPECT_TRUE(carrier2.headers_.count("traceparent") > 0);
+ EXPECT_TRUE(carrier2.headers_.count("tracestate") > 0);
+ EXPECT_EQ(carrier2.headers_["tracestate"], "congo=t61rcWkgMzE");
+}
+
+TEST(TextMapPropagatorTest, PropagateInvalidContext)
+{
+ // Do not propagate invalid trace context.
+ TextMapCarrierTest carrier;
+ context::Context ctx{
+ "current-span",
+ nostd::shared_ptr<trace::Span>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
+ format.Inject(carrier, ctx);
+ EXPECT_TRUE(carrier.headers_.count("traceparent") == 0);
+ EXPECT_TRUE(carrier.headers_.count("tracestate") == 0);
+}
+
+TEST(TextMapPropagatorTest, SetRemoteSpan)
+{
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
+ EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
+
+ auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
+
+ EXPECT_EQ(Hex(span->GetContext().trace_id()), "4bf92f3577b34da6a3ce929d0e0e4736");
+ EXPECT_EQ(Hex(span->GetContext().span_id()), "0102030405060708");
+ EXPECT_EQ(span->GetContext().IsSampled(), true);
+ EXPECT_EQ(span->GetContext().IsRemote(), true);
+}
+
+TEST(TextMapPropagatorTest, GetCurrentSpan)
+{
+ TextMapCarrierTest carrier;
+ constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+
+ auto trace_state = trace::TraceState::FromHeader("congo=t61rcWkgMzE");
+ trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span},
+ trace::TraceFlags{true}, false, trace_state};
+ nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}};
+
+ // Set `sp` as the currently active span, which must be used by `Inject`.
+ trace::Scope scoped_span{sp};
+
+ format.Inject(carrier, context::RuntimeContext::GetCurrent());
+ EXPECT_EQ(carrier.headers_["traceparent"],
+ "00-0102030405060708090a0b0c0d0e0f10-0102030405060708-01");
+ EXPECT_EQ(carrier.headers_["tracestate"], "congo=t61rcWkgMzE");
+}
+
+TEST(TextMapPropagatorTest, InvalidIdentitiesAreNotExtracted)
+{
+ TextMapCarrierTest carrier;
+ std::vector<std::string> traces = {
+ "ff-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01",
+ "00-0af7651916cd43dd8448eb211c80319c1-b9c7c989f97918e1-01",
+ "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e11-01",
+ "0-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01",
+ "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-0",
+ "00-0af7651916cd43dd8448eb211c8031-b9c7c989f97918e1-01",
+ "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97-01",
+ "00-1-1-00",
+ "00--b9c7c989f97918e1-01",
+ "00-0af7651916cd43dd8448eb211c80319c1--01",
+ "",
+ "---",
+ };
+
+ for (auto &trace : traces)
+ {
+ carrier.headers_ = {{"traceparent", trace}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ auto span = trace::GetSpan(ctx2)->GetContext();
+ EXPECT_FALSE(span.IsValid());
+ }
+}
+
+TEST(GlobalTextMapPropagator, NoOpPropagator)
+{
+
+ auto propagator = context::propagation::GlobalTextMapPropagator::GetGlobalPropagator();
+ TextMapCarrierTest carrier;
+
+ carrier.headers_ = {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"},
+ {"tracestate", "congo=t61rcWkgMzE"}};
+ context::Context ctx1 = context::Context{
+ "current-span",
+ nostd::shared_ptr<trace::Span>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
+ context::Context ctx2 = propagator->Extract(carrier, ctx1);
+
+ TextMapCarrierTest carrier2;
+ propagator->Inject(carrier2, ctx2);
+
+ EXPECT_TRUE(carrier2.headers_.count("tracestate") == 0);
+ EXPECT_TRUE(carrier2.headers_.count("traceparent") == 0);
+}
+
+TEST(GlobalPropagator, SetAndGet)
+{
+
+ auto trace_state_value = "congo=t61rcWkgMzE";
+ context::propagation::GlobalTextMapPropagator::SetGlobalPropagator(
+ nostd::shared_ptr<context::propagation::TextMapPropagator>(new MapHttpTraceContext()));
+
+ auto propagator = context::propagation::GlobalTextMapPropagator::GetGlobalPropagator();
+
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"},
+ {"tracestate", trace_state_value}};
+ context::Context ctx1 = context::Context{
+ "current-span",
+ nostd::shared_ptr<trace::Span>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
+ context::Context ctx2 = propagator->Extract(carrier, ctx1);
+
+ TextMapCarrierTest carrier2;
+ propagator->Inject(carrier2, ctx2);
+
+ EXPECT_TRUE(carrier.headers_.count("traceparent") > 0);
+ EXPECT_TRUE(carrier.headers_.count("tracestate") > 0);
+ EXPECT_EQ(carrier.headers_["tracestate"], trace_state_value);
+
+ std::vector<std::string> fields;
+ propagator->Fields([&fields](nostd::string_view field) {
+ fields.push_back(field.data());
+ return true;
+ });
+ EXPECT_EQ(fields.size(), 2);
+ EXPECT_EQ(fields[0], trace::propagation::kTraceParent);
+ EXPECT_EQ(fields[1], trace::propagation::kTraceState);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/jaeger_propagation_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/jaeger_propagation_test.cc
new file mode 100644
index 000000000..c33761738
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/jaeger_propagation_test.cc
@@ -0,0 +1,168 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/propagation/jaeger.h"
+#include "opentelemetry/trace/scope.h"
+#include "util.h"
+
+#include <map>
+
+#include <gtest/gtest.h>
+
+using namespace opentelemetry;
+
+class TextMapCarrierTest : public context::propagation::TextMapCarrier
+{
+public:
+ virtual nostd::string_view Get(nostd::string_view key) const noexcept override
+ {
+ auto it = headers_.find(std::string(key));
+ if (it != headers_.end())
+ {
+ return nostd::string_view(it->second);
+ }
+ return "";
+ }
+ virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override
+ {
+ headers_[std::string(key)] = std::string(value);
+ }
+
+ std::map<std::string, std::string> headers_;
+};
+
+using Propagator = trace::propagation::JaegerPropagator;
+
+static Propagator format = Propagator();
+
+TEST(JaegerPropagatorTest, ExtractValidSpans)
+{
+ struct TestTrace
+ {
+ std::string trace_state;
+ std::string expected_trace_id;
+ std::string expected_span_id;
+ bool sampled;
+ };
+
+ std::vector<TestTrace> traces = {
+ {
+ "4bf92f3577b34da6a3ce929d0e0e4736:0102030405060708:0:00",
+ "4bf92f3577b34da6a3ce929d0e0e4736",
+ "0102030405060708",
+ false,
+ },
+ {
+ "4bf92f3577b34da6a3ce929d0e0e4736:0102030405060708:0:ff",
+ "4bf92f3577b34da6a3ce929d0e0e4736",
+ "0102030405060708",
+ true,
+ },
+ {
+ "4bf92f3577b34da6a3ce929d0e0e4736:0102030405060708:0:f",
+ "4bf92f3577b34da6a3ce929d0e0e4736",
+ "0102030405060708",
+ true,
+ },
+ {
+ "a3ce929d0e0e4736:0102030405060708:0:00",
+ "0000000000000000a3ce929d0e0e4736",
+ "0102030405060708",
+ false,
+ },
+ {
+ "A3CE929D0E0E4736:ABCDEFABCDEF1234:0:01",
+ "0000000000000000a3ce929d0e0e4736",
+ "abcdefabcdef1234",
+ true,
+ },
+ {
+ "ff:ABCDEFABCDEF1234:0:0",
+ "000000000000000000000000000000ff",
+ "abcdefabcdef1234",
+ false,
+ },
+ {
+ "4bf92f3577b34da6a3ce929d0e0e4736:0102030405060708:0102030405060708:00",
+ "4bf92f3577b34da6a3ce929d0e0e4736",
+ "0102030405060708",
+ false,
+ },
+
+ };
+
+ for (TestTrace &test_trace : traces)
+ {
+ TextMapCarrierTest carrier;
+ carrier.headers_ = {{"uber-trace-id", test_trace.trace_state}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ auto span = trace::GetSpan(ctx2)->GetContext();
+ EXPECT_TRUE(span.IsValid());
+
+ EXPECT_EQ(Hex(span.trace_id()), test_trace.expected_trace_id);
+ EXPECT_EQ(Hex(span.span_id()), test_trace.expected_span_id);
+ EXPECT_EQ(span.IsSampled(), test_trace.sampled);
+ EXPECT_EQ(span.IsRemote(), true);
+ }
+}
+
+TEST(JaegerPropagatorTest, ExctractInvalidSpans)
+{
+ TextMapCarrierTest carrier;
+ std::vector<std::string> traces = {
+ "4bf92f3577b34da6a3ce929d0e0e47344:0102030405060708:0:00", // too long trace id
+ "4bf92f3577b34da6a3ce929d0e0e4734:01020304050607089:0:00", // too long span id
+ "4bf92f3577b34da6x3ce929d0y0e4734:01020304050607089:0:00", // invalid trace id character
+ "4bf92f3577b34da6a3ce929d0e0e4734:01020304g50607089:0:00", // invalid span id character
+ "4bf92f3577b34da6a3ce929d0e0e4734::0:00",
+ "",
+ "::::",
+ "0:0:0:0",
+ ":abcdef12:0:0",
+ };
+
+ for (auto &trace : traces)
+ {
+ carrier.headers_ = {{"uber-trace-id", trace}};
+ context::Context ctx1 = context::Context{};
+ context::Context ctx2 = format.Extract(carrier, ctx1);
+
+ auto span = trace::GetSpan(ctx2)->GetContext();
+ EXPECT_FALSE(span.IsValid());
+ }
+}
+
+TEST(JaegerPropagatorTest, InjectsContext)
+{
+ TextMapCarrierTest carrier;
+ constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+ trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span},
+ trace::TraceFlags{true}, false};
+ nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}};
+ trace::Scope scoped_span{sp};
+
+ format.Inject(carrier, context::RuntimeContext::GetCurrent());
+ EXPECT_EQ(carrier.headers_["uber-trace-id"],
+ "0102030405060708090a0b0c0d0e0f10:0102030405060708:0:01");
+
+ std::vector<std::string> fields;
+ format.Fields([&fields](nostd::string_view field) {
+ fields.push_back(field.data());
+ return true;
+ });
+ EXPECT_EQ(fields.size(), 1);
+ EXPECT_EQ(fields[0], opentelemetry::trace::propagation::kJaegerTraceHeader);
+}
+
+TEST(JaegerPropagatorTest, DoNotInjectInvalidContext)
+{
+ TextMapCarrierTest carrier;
+ context::Context ctx{
+ "current-span",
+ nostd::shared_ptr<trace::Span>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
+ format.Inject(carrier, ctx);
+ EXPECT_TRUE(carrier.headers_.count("uber-trace-id") == 0);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/util.h b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/util.h
new file mode 100644
index 000000000..ae234d92e
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/util.h
@@ -0,0 +1,14 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <string>
+
+template <typename T>
+static std::string Hex(const T &id_item)
+{
+ char buf[T::kSize * 2];
+ id_item.ToLowerBase16(buf);
+ return std::string(buf, sizeof(buf));
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/provider_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/provider_test.cc
new file mode 100644
index 000000000..9e5a7aad1
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/provider_test.cc
@@ -0,0 +1,36 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/provider.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+
+#include <gtest/gtest.h>
+
+using opentelemetry::trace::Provider;
+using opentelemetry::trace::Tracer;
+using opentelemetry::trace::TracerProvider;
+
+namespace nostd = opentelemetry::nostd;
+
+class TestProvider : public TracerProvider
+{
+ nostd::shared_ptr<Tracer> GetTracer(nostd::string_view library_name,
+ nostd::string_view library_version,
+ nostd::string_view schema_url) noexcept override
+ {
+ return nostd::shared_ptr<Tracer>(nullptr);
+ }
+};
+
+TEST(Provider, GetTracerProviderDefault)
+{
+ auto tf = Provider::GetTracerProvider();
+ EXPECT_NE(nullptr, tf);
+}
+
+TEST(Provider, SetTracerProvider)
+{
+ auto tf = nostd::shared_ptr<TracerProvider>(new TestProvider());
+ Provider::SetTracerProvider(tf);
+ ASSERT_EQ(tf, Provider::GetTracerProvider());
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/scope_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/scope_test.cc
new file mode 100644
index 000000000..b74905b16
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/scope_test.cc
@@ -0,0 +1,51 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/scope.h"
+#include "opentelemetry/context/context.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/trace/noop.h"
+
+#include <gtest/gtest.h>
+
+using opentelemetry::trace::kSpanKey;
+using opentelemetry::trace::NoopSpan;
+using opentelemetry::trace::Scope;
+using opentelemetry::trace::Span;
+namespace nostd = opentelemetry::nostd;
+namespace context = opentelemetry::context;
+
+TEST(ScopeTest, Construct)
+{
+ nostd::shared_ptr<Span> span(new NoopSpan(nullptr));
+ Scope scope(span);
+
+ context::ContextValue active_span_value = context::RuntimeContext::GetValue(kSpanKey);
+ ASSERT_TRUE(nostd::holds_alternative<nostd::shared_ptr<Span>>(active_span_value));
+
+ auto active_span = nostd::get<nostd::shared_ptr<Span>>(active_span_value);
+ ASSERT_EQ(active_span, span);
+}
+
+TEST(ScopeTest, Destruct)
+{
+ nostd::shared_ptr<Span> span(new NoopSpan(nullptr));
+ Scope scope(span);
+
+ {
+ nostd::shared_ptr<Span> span_nested(new NoopSpan(nullptr));
+ Scope scope_nested(span_nested);
+
+ context::ContextValue active_span_value = context::RuntimeContext::GetValue(kSpanKey);
+ ASSERT_TRUE(nostd::holds_alternative<nostd::shared_ptr<Span>>(active_span_value));
+
+ auto active_span = nostd::get<nostd::shared_ptr<Span>>(active_span_value);
+ ASSERT_EQ(active_span, span_nested);
+ }
+
+ context::ContextValue active_span_value = context::RuntimeContext::GetValue(kSpanKey);
+ ASSERT_TRUE(nostd::holds_alternative<nostd::shared_ptr<Span>>(active_span_value));
+
+ auto active_span = nostd::get<nostd::shared_ptr<Span>>(active_span_value);
+ ASSERT_EQ(active_span, span);
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_benchmark.cc
new file mode 100644
index 000000000..ef14cd4ca
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_benchmark.cc
@@ -0,0 +1,129 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/trace/context.h"
+#include "opentelemetry/trace/noop.h"
+#include "opentelemetry/trace/span_id.h"
+#include "opentelemetry/trace/trace_id.h"
+
+#include <cstdint>
+
+#include <benchmark/benchmark.h>
+
+using opentelemetry::trace::SpanContext;
+namespace trace_api = opentelemetry::trace;
+namespace nostd = opentelemetry::nostd;
+namespace context = opentelemetry::context;
+
+namespace
+{
+
+std::shared_ptr<trace_api::Tracer> initTracer()
+{
+ return std::shared_ptr<trace_api::Tracer>(new trace_api::NoopTracer());
+}
+
+// Test to measure performance for span creation
+void BM_SpanCreation(benchmark::State &state)
+{
+ auto tracer = initTracer();
+ while (state.KeepRunning())
+ {
+ auto span = tracer->StartSpan("span");
+ span->End();
+ }
+}
+BENCHMARK(BM_SpanCreation);
+
+// Test to measure performance for single span creation with scope
+void BM_SpanCreationWithScope(benchmark::State &state)
+{
+ auto tracer = initTracer();
+ while (state.KeepRunning())
+ {
+ auto span = tracer->StartSpan("span");
+ auto scope = tracer->WithActiveSpan(span);
+ span->End();
+ }
+}
+BENCHMARK(BM_SpanCreationWithScope);
+
+// Test to measure performance for nested span creation with scope
+void BM_NestedSpanCreationWithScope(benchmark::State &state)
+{
+ auto tracer = initTracer();
+ while (state.KeepRunning())
+ {
+ auto span = tracer->StartSpan("outer");
+ auto scope = tracer->WithActiveSpan(span);
+ {
+ auto span = tracer->StartSpan("inner");
+ auto scope = tracer->WithActiveSpan(span);
+ {
+ auto span = tracer->StartSpan("innermost");
+ auto scope = tracer->WithActiveSpan(span);
+ span->End();
+ }
+ span->End();
+ }
+ span->End();
+ }
+}
+
+BENCHMARK(BM_NestedSpanCreationWithScope);
+
+// Test to measure performance for nested span creation with manual span context management
+void BM_SpanCreationWithManualSpanContextPropagation(benchmark::State &state)
+{
+ auto tracer = initTracer();
+ constexpr uint8_t buf1[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ trace_api::SpanId span_id(buf1);
+ constexpr uint8_t buf2[] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1};
+ trace_api::TraceId trace_id(buf2);
+
+ while (state.KeepRunning())
+ {
+ auto outer_span = nostd::shared_ptr<trace_api::Span>(
+ new trace_api::DefaultSpan(SpanContext(trace_id, span_id, trace_api::TraceFlags(), false)));
+ trace_api::StartSpanOptions options;
+ options.parent = outer_span->GetContext();
+ auto inner_span = tracer->StartSpan("inner", options);
+ auto inner_span_context = inner_span->GetContext();
+ options.parent = inner_span_context;
+ auto innermost_span = tracer->StartSpan("innermost", options);
+ innermost_span->End();
+ inner_span->End();
+ }
+}
+BENCHMARK(BM_SpanCreationWithManualSpanContextPropagation);
+
+// Test to measure performance for nested span creation with context propagation
+void BM_SpanCreationWitContextPropagation(benchmark::State &state)
+{
+ auto tracer = initTracer();
+ constexpr uint8_t buf1[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ trace_api::SpanId span_id(buf1);
+ constexpr uint8_t buf2[] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1};
+ trace_api::TraceId trace_id(buf2);
+
+ while (state.KeepRunning())
+ {
+ auto current_ctx = context::RuntimeContext::GetCurrent();
+ auto outer_span_context = SpanContext(trace_id, span_id, trace_api::TraceFlags(), false);
+ auto outer_span =
+ nostd::shared_ptr<trace_api::Span>(new trace_api::DefaultSpan(outer_span_context));
+ trace_api::SetSpan(current_ctx, outer_span);
+ auto inner_child = tracer->StartSpan("inner");
+ auto scope = tracer->WithActiveSpan(inner_child);
+ {
+ auto innermost_child = tracer->StartSpan("innermost");
+ auto scope = tracer->WithActiveSpan(innermost_child);
+ innermost_child->End();
+ }
+ inner_child->End();
+ }
+}
+BENCHMARK(BM_SpanCreationWitContextPropagation);
+} // namespace
+BENCHMARK_MAIN();
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_context_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_context_test.cc
new file mode 100644
index 000000000..a3fd9a84a
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_context_test.cc
@@ -0,0 +1,55 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/span_context.h"
+#include "opentelemetry/trace/span_id.h"
+#include "opentelemetry/trace/trace_id.h"
+
+#include <gtest/gtest.h>
+
+using opentelemetry::trace::SpanContext;
+namespace trace_api = opentelemetry::trace;
+
+TEST(SpanContextTest, IsSampled)
+{
+ SpanContext s1(true, true);
+
+ ASSERT_EQ(s1.IsSampled(), true);
+
+ SpanContext s2(false, true);
+
+ ASSERT_EQ(s2.IsSampled(), false);
+}
+
+TEST(SpanContextTest, IsRemote)
+{
+ SpanContext s1(true, true);
+
+ ASSERT_EQ(s1.IsRemote(), true);
+
+ SpanContext s2(true, false);
+
+ ASSERT_EQ(s2.IsRemote(), false);
+}
+
+TEST(SpanContextTest, TraceFlags)
+{
+ SpanContext s1(true, true);
+
+ ASSERT_EQ(s1.trace_flags().flags(), 1);
+
+ SpanContext s2(false, true);
+
+ ASSERT_EQ(s2.trace_flags().flags(), 0);
+}
+
+// Test that SpanContext is invalid
+TEST(SpanContextTest, Invalid)
+{
+ SpanContext s1 = SpanContext::GetInvalid();
+ EXPECT_FALSE(s1.IsValid());
+
+ // Test that trace id and span id are invalid
+ EXPECT_EQ(s1.trace_id(), trace_api::TraceId());
+ EXPECT_EQ(s1.span_id(), trace_api::SpanId());
+}
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_benchmark.cc
new file mode 100644
index 000000000..42d4aeb46
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_benchmark.cc
@@ -0,0 +1,55 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/span_id.h"
+
+#include <benchmark/benchmark.h>
+#include <cstdint>
+
+namespace
+{
+using opentelemetry::trace::SpanId;
+constexpr uint8_t bytes[] = {1, 2, 3, 4, 5, 6, 7, 8};
+
+void BM_SpanIdDefaultConstructor(benchmark::State &state)
+{
+ while (state.KeepRunning())
+ {
+ benchmark::DoNotOptimize(SpanId());
+ }
+}
+BENCHMARK(BM_SpanIdDefaultConstructor);
+
+void BM_SpanIdConstructor(benchmark::State &state)
+{
+ while (state.KeepRunning())
+ {
+ benchmark::DoNotOptimize(SpanId(bytes));
+ }
+}
+BENCHMARK(BM_SpanIdConstructor);
+
+void BM_SpanIdToLowerBase16(benchmark::State &state)
+{
+ SpanId id(bytes);
+ char buf[SpanId::kSize * 2];
+ while (state.KeepRunning())
+ {
+ id.ToLowerBase16(buf);
+ benchmark::DoNotOptimize(buf);
+ }
+}
+BENCHMARK(BM_SpanIdToLowerBase16);
+
+void BM_SpanIdIsValid(benchmark::State &state)
+{
+ SpanId id(bytes);
+ while (state.KeepRunning())
+ {
+ benchmark::DoNotOptimize(id.IsValid());
+ }
+}
+BENCHMARK(BM_SpanIdIsValid);
+
+} // namespace
+BENCHMARK_MAIN();
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_test.cc
new file mode 100644
index 000000000..52bb9b7de
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_test.cc
@@ -0,0 +1,58 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/span_id.h"
+
+#include <cstring>
+#include <string>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using opentelemetry::trace::SpanId;
+
+std::string Hex(const opentelemetry::trace::SpanId &span)
+{
+ char buf[16];
+ span.ToLowerBase16(buf);
+ return std::string(buf, sizeof(buf));
+}
+
+TEST(SpanIdTest, DefaultConstruction)
+{
+ SpanId id;
+ EXPECT_FALSE(id.IsValid());
+ EXPECT_EQ("0000000000000000", Hex(id));
+}
+
+TEST(SpanIdTest, ValidId)
+{
+ constexpr uint8_t buf[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ SpanId id(buf);
+ EXPECT_TRUE(id.IsValid());
+ EXPECT_EQ("0102030405060708", Hex(id));
+ EXPECT_NE(SpanId(), id);
+ EXPECT_EQ(SpanId(buf), id);
+}
+
+TEST(SpanIdTest, LowercaseBase16)
+{
+ constexpr uint8_t buf[] = {1, 2, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
+ SpanId id(buf);
+ EXPECT_TRUE(id.IsValid());
+ EXPECT_EQ("0102aabbccddeeff", Hex(id));
+ EXPECT_NE(SpanId(), id);
+ EXPECT_EQ(SpanId(buf), id);
+}
+
+TEST(SpanIdTest, CopyBytesTo)
+{
+ constexpr uint8_t src[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ SpanId id(src);
+ uint8_t buf[8];
+ id.CopyBytesTo(buf);
+ EXPECT_TRUE(memcmp(src, buf, 8) == 0);
+}
+} // namespace
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_flags_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_flags_test.cc
new file mode 100644
index 000000000..783b56d83
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_flags_test.cc
@@ -0,0 +1,43 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/trace_flags.h"
+
+#include <cstring>
+#include <string>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using opentelemetry::trace::TraceFlags;
+
+std::string Hex(const TraceFlags &flags)
+{
+ char buf[2];
+ flags.ToLowerBase16(buf);
+ return std::string(buf, sizeof(buf));
+}
+
+TEST(TraceFlagsTest, DefaultConstruction)
+{
+ TraceFlags flags;
+ EXPECT_FALSE(flags.IsSampled());
+ EXPECT_EQ(0, flags.flags());
+ EXPECT_EQ("00", Hex(flags));
+}
+
+TEST(TraceFlagsTest, Sampled)
+{
+ TraceFlags flags{TraceFlags::kIsSampled};
+ EXPECT_TRUE(flags.IsSampled());
+ EXPECT_EQ(1, flags.flags());
+ EXPECT_EQ("01", Hex(flags));
+
+ uint8_t buf[1];
+ flags.CopyBytesTo(buf);
+ EXPECT_EQ(1, buf[0]);
+}
+
+} // namespace
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_id_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_id_test.cc
new file mode 100644
index 000000000..f903bfe9e
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_id_test.cc
@@ -0,0 +1,58 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/trace_id.h"
+
+#include <cstring>
+#include <string>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using opentelemetry::trace::TraceId;
+
+std::string Hex(const opentelemetry::trace::TraceId &trace)
+{
+ char buf[32];
+ trace.ToLowerBase16(buf);
+ return std::string(buf, sizeof(buf));
+}
+
+TEST(TraceIdTest, DefaultConstruction)
+{
+ TraceId id;
+ EXPECT_FALSE(id.IsValid());
+ EXPECT_EQ("00000000000000000000000000000000", Hex(id));
+}
+
+TEST(TraceIdTest, ValidId)
+{
+ constexpr uint8_t buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1};
+ TraceId id(buf);
+ EXPECT_TRUE(id.IsValid());
+ EXPECT_EQ("01020304050607080807060504030201", Hex(id));
+ EXPECT_NE(TraceId(), id);
+ EXPECT_EQ(TraceId(buf), id);
+}
+
+TEST(TraceIdTest, LowercaseBase16)
+{
+ constexpr uint8_t buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
+ TraceId id(buf);
+ EXPECT_TRUE(id.IsValid());
+ EXPECT_EQ("01020304050607080807aabbccddeeff", Hex(id));
+ EXPECT_NE(TraceId(), id);
+ EXPECT_EQ(TraceId(buf), id);
+}
+
+TEST(TraceIdTest, CopyBytesTo)
+{
+ constexpr uint8_t src[] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1};
+ TraceId id(src);
+ uint8_t buf[TraceId::kSize];
+ id.CopyBytesTo(buf);
+ EXPECT_TRUE(memcmp(src, buf, sizeof(buf)) == 0);
+}
+} // namespace
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_state_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_state_test.cc
new file mode 100644
index 000000000..ed6c7e827
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_state_test.cc
@@ -0,0 +1,196 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/trace/trace_state.h"
+
+#include <gtest/gtest.h>
+#include "opentelemetry/nostd/string_view.h"
+
+namespace
+{
+
+using opentelemetry::trace::TraceState;
+namespace nostd = opentelemetry::nostd;
+
+// Random string of length 257. Used for testing strings with max length 256.
+const char *kLongString =
+ "4aekid3he76zgytjavudqqeltyvu5zqio2lx7d92dlxlf0z4883irvxuwelsq27sx1mlrjg3r7ad3jeq09rjppyd9veorg"
+ "2nmihy4vilabfts8bsxruih0urusmjnglzl3iwpjinmo835dbojcrd73p56nw80v4xxrkye59ytmu5v84ysfa24d58ovv9"
+ "w1n54n0mhhf4z0mpv6oudywrp9vfoks6lrvxv3uihvbi2ihazf237kvt1nbsjn3kdvfdb";
+
+// -------------------------- TraceState class tests ---------------------------
+
+std::string create_ts_return_header(std::string header)
+{
+ auto ts = TraceState::FromHeader(header);
+ return ts->ToHeader();
+}
+
+std::string header_with_max_members()
+{
+ std::string header = "";
+ auto max_members = TraceState::kMaxKeyValuePairs;
+ for (int i = 0; i < max_members; i++)
+ {
+ std::string key = "key" + std::to_string(i);
+ std::string value = "value" + std::to_string(i);
+ header += key + "=" + value;
+ if (i != max_members - 1)
+ {
+ header += ",";
+ }
+ }
+ return header;
+}
+
+TEST(TraceStateTest, ValidateHeaderParsing)
+{
+ auto max_trace_state_header = header_with_max_members();
+
+ struct
+ {
+ const char *input;
+ const char *expected;
+ } testcases[] = {{"k1=v1", "k1=v1"},
+ {"K1=V1", ""},
+ {"k1=v1,k2=v2,k3=v3", "k1=v1,k2=v2,k3=v3"},
+ {"k1=v1,k2=v2,,", "k1=v1,k2=v2"},
+ {"k1=v1,k2=v2,invalidmember", ""},
+ {"1a-2f@foo=bar1,a*/foo-_/bar=bar4", "1a-2f@foo=bar1,a*/foo-_/bar=bar4"},
+ {"1a-2f@foo=bar1,*/foo-_/bar=bar4", ""},
+ {",k1=v1", "k1=v1"},
+ {",", ""},
+ {",=,", ""},
+ {"", ""},
+ {max_trace_state_header.data(), max_trace_state_header.data()}};
+ for (auto &testcase : testcases)
+ {
+ EXPECT_EQ(create_ts_return_header(testcase.input), testcase.expected);
+ }
+}
+
+TEST(TraceStateTest, TraceStateGet)
+{
+
+ std::string trace_state_header = header_with_max_members();
+ auto ts = TraceState::FromHeader(trace_state_header);
+
+ std::string value;
+ EXPECT_TRUE(ts->Get("key0", value));
+ EXPECT_EQ(value, "value0");
+ EXPECT_TRUE(ts->Get("key16", value));
+ EXPECT_EQ(value, "value16");
+ EXPECT_TRUE(ts->Get("key31", value));
+ EXPECT_EQ(value, "value31");
+ EXPECT_FALSE(ts->Get("key32", value));
+}
+
+TEST(TraceStateTest, TraceStateSet)
+{
+ std::string trace_state_header = "k1=v1,k2=v2";
+ auto ts1 = TraceState::FromHeader(trace_state_header);
+ auto ts1_new = ts1->Set("k3", "v3");
+ EXPECT_EQ(ts1_new->ToHeader(), "k3=v3,k1=v1,k2=v2");
+
+ trace_state_header = header_with_max_members();
+ auto ts2 = TraceState::FromHeader(trace_state_header);
+ auto ts2_new =
+ ts2->Set("n_k1", "n_v1"); // adding to max list, should return copy of existing list
+ EXPECT_EQ(ts2_new->ToHeader(), trace_state_header);
+
+ trace_state_header = "k1=v1,k2=v2";
+ auto ts3 = TraceState::FromHeader(trace_state_header);
+ auto ts3_new = ts3->Set("*n_k1", "n_v1"); // adding invalid key, should return empty
+ EXPECT_EQ(ts3_new->ToHeader(), "");
+}
+
+TEST(TraceStateTest, TraceStateDelete)
+{
+ std::string trace_state_header = "k1=v1,k2=v2,k3=v3";
+ auto ts1 = TraceState::FromHeader(trace_state_header);
+ auto ts1_new = ts1->Delete(std::string("k1"));
+ EXPECT_EQ(ts1_new->ToHeader(), "k2=v2,k3=v3");
+
+ trace_state_header = "k1=v1"; // single list member
+ auto ts2 = TraceState::FromHeader(trace_state_header);
+ auto ts2_new = ts2->Delete(std::string("k1"));
+ EXPECT_EQ(ts2_new->ToHeader(), "");
+
+ trace_state_header = "k1=v1"; // single list member, delete invalid entry
+ auto ts3 = TraceState::FromHeader(trace_state_header);
+ auto ts3_new = ts3->Delete(std::string("InvalidKey"));
+ EXPECT_EQ(ts3_new->ToHeader(), "");
+}
+
+TEST(TraceStateTest, Empty)
+{
+ std::string trace_state_header = "";
+ auto ts = TraceState::FromHeader(trace_state_header);
+ EXPECT_TRUE(ts->Empty());
+
+ trace_state_header = "k1=v1,k2=v2";
+ auto ts1 = TraceState::FromHeader(trace_state_header);
+ EXPECT_FALSE(ts1->Empty());
+}
+
+TEST(TraceStateTest, GetAllEntries)
+{
+ std::string trace_state_header = "k1=v1,k2=v2,k3=v3";
+ auto ts1 = TraceState::FromHeader(trace_state_header);
+ const int kNumPairs = 3;
+ nostd::string_view keys[kNumPairs] = {"k1", "k2", "k3"};
+ nostd::string_view values[kNumPairs] = {"v1", "v2", "v3"};
+ size_t index = 0;
+ ts1->GetAllEntries([&keys, &values, &index](nostd::string_view key, nostd::string_view value) {
+ EXPECT_EQ(key, keys[index]);
+ EXPECT_EQ(value, values[index]);
+ index++;
+ return true;
+ });
+}
+
+TEST(TraceStateTest, IsValidKey)
+{
+ EXPECT_TRUE(TraceState::IsValidKey("valid-key23/*"));
+ EXPECT_FALSE(TraceState::IsValidKey("Invalid_key"));
+ EXPECT_FALSE(TraceState::IsValidKey("invalid$Key&"));
+ EXPECT_FALSE(TraceState::IsValidKey(""));
+ EXPECT_FALSE(TraceState::IsValidKey(kLongString));
+}
+
+TEST(TraceStateTest, IsValidValue)
+{
+ EXPECT_TRUE(TraceState::IsValidValue("valid-val$%&~"));
+ EXPECT_FALSE(TraceState::IsValidValue("\tinvalid"));
+ EXPECT_FALSE(TraceState::IsValidValue("invalid="));
+ EXPECT_FALSE(TraceState::IsValidValue("invalid,val"));
+ EXPECT_FALSE(TraceState::IsValidValue(""));
+ EXPECT_FALSE(TraceState::IsValidValue(kLongString));
+}
+
+// Tests that keys and values don't depend on null terminators
+TEST(TraceStateTest, MemorySafe)
+{
+ std::string trace_state_header = "";
+ auto ts = TraceState::FromHeader(trace_state_header);
+ const int kNumPairs = 3;
+ nostd::string_view key_string = "test_key_1test_key_2test_key_3";
+ nostd::string_view val_string = "test_val_1test_val_2test_val_3";
+ nostd::string_view keys[kNumPairs] = {key_string.substr(0, 10), key_string.substr(10, 10),
+ key_string.substr(20, 10)};
+ nostd::string_view values[kNumPairs] = {val_string.substr(0, 10), val_string.substr(10, 10),
+ val_string.substr(20, 10)};
+
+ auto ts1 = ts->Set(keys[2], values[2]);
+ auto ts2 = ts1->Set(keys[1], values[1]);
+ auto ts3 = ts2->Set(keys[0], values[0]);
+ size_t index = 0;
+
+ ts3->GetAllEntries([&keys, &values, &index](nostd::string_view key, nostd::string_view value) {
+ EXPECT_EQ(key, keys[index]);
+ EXPECT_EQ(value, values[index]);
+ index++;
+ return true;
+ });
+}
+} // namespace
diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/trace/tracer_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/trace/tracer_test.cc
new file mode 100644
index 000000000..8e16f15e2
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/test/trace/tracer_test.cc
@@ -0,0 +1,39 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/trace/noop.h"
+#include "opentelemetry/trace/scope.h"
+
+#include <gtest/gtest.h>
+
+namespace trace_api = opentelemetry::trace;
+namespace nostd = opentelemetry::nostd;
+namespace context = opentelemetry::context;
+
+TEST(TracerTest, GetCurrentSpan)
+{
+ std::unique_ptr<trace_api::Tracer> tracer(new trace_api::NoopTracer());
+ nostd::shared_ptr<trace_api::Span> span_first(new trace_api::NoopSpan(nullptr));
+ nostd::shared_ptr<trace_api::Span> span_second(new trace_api::NoopSpan(nullptr));
+
+ auto current = tracer->GetCurrentSpan();
+ ASSERT_FALSE(current->GetContext().IsValid());
+
+ {
+ auto scope_first = tracer->WithActiveSpan(span_first);
+ current = tracer->GetCurrentSpan();
+ ASSERT_EQ(current, span_first);
+
+ {
+ auto scope_second = tracer->WithActiveSpan(span_second);
+ current = tracer->GetCurrentSpan();
+ ASSERT_EQ(current, span_second);
+ }
+ current = tracer->GetCurrentSpan();
+ ASSERT_EQ(current, span_first);
+ }
+
+ current = tracer->GetCurrentSpan();
+ ASSERT_FALSE(current->GetContext().IsValid());
+}