// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #include #include #include #include #include #include #include #include #include "opentelemetry/context/context.h" #include "opentelemetry/context/context_value.h" #include "opentelemetry/context/runtime_context.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/nostd/unique_ptr.h" #include "opentelemetry/nostd/variant.h" using namespace opentelemetry; // Tests that GetCurrent returns the current context TEST(RuntimeContextTest, GetCurrent) { std::map map_test = {{"test_key", static_cast(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 map_test = {{"test_key", static_cast(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 map_test = {{"test_key", static_cast(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 map_test = {{"test_key", static_cast(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", static_cast(596)); auto old_context_token = context::RuntimeContext::Attach(foo_context); context::Context test_context = context::RuntimeContext::SetValue("test_key", static_cast(123)); EXPECT_EQ(nostd::get(test_context.GetValue("test_key")), 123); EXPECT_EQ(nostd::get(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", static_cast(596)); context::Context test_context = context::RuntimeContext::SetValue("test_key", static_cast(123), &foo_context); EXPECT_EQ(nostd::get(test_context.GetValue("test_key")), 123); EXPECT_EQ(nostd::get(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", static_cast(596)); auto old_context_token = context::RuntimeContext::Attach(foo_context); EXPECT_EQ(nostd::get(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", static_cast(596)); EXPECT_EQ(nostd::get(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 indices; indices.push_back(0); indices.push_back(1); indices.push_back(2); indices.push_back(3); std::vector contexts; contexts.reserve(indices.size()); for (auto i : indices) { contexts.push_back(context::Context("index", static_cast(i))); } do { std::vector> tokens; tokens.reserve(contexts.size()); 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())); }