opentelemetry-cpp/api/test/context/runtime_context_test.cc

150 lines
5.9 KiB
C++

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#include <gtest/gtest.h>
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <map>
#include <string>
#include <utility>
#include <vector>
#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<std::string, context::ContextValue> map_test = {{"test_key", static_cast<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", static_cast<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", static_cast<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", static_cast<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", static_cast<int64_t>(596));
auto old_context_token = context::RuntimeContext::Attach(foo_context);
context::Context test_context =
context::RuntimeContext::SetValue("test_key", static_cast<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", static_cast<int64_t>(596));
context::Context test_context =
context::RuntimeContext::SetValue("test_key", static_cast<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", static_cast<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", static_cast<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;
contexts.reserve(indices.size());
for (auto i : indices)
{
contexts.push_back(context::Context("index", static_cast<int64_t>(i)));
}
do
{
std::vector<nostd::unique_ptr<context::Token>> 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()));
}