summaryrefslogtreecommitdiffstats
path: root/src/jaegertracing/opentelemetry-cpp/api/test/trace
diff options
context:
space:
mode:
Diffstat (limited to 'src/jaegertracing/opentelemetry-cpp/api/test/trace')
-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
21 files changed, 1765 insertions, 0 deletions
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());
+}