diff options
Diffstat (limited to 'src/jaegertracing/opentelemetry-cpp/api/test/context')
7 files changed, 475 insertions, 0 deletions
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())); +} |