diff --git a/opentracing-shim/include/shim_utils.h b/opentracing-shim/include/shim_utils.h index 9fbd71dbc9..87e1951140 100644 --- a/opentracing-shim/include/shim_utils.h +++ b/opentracing-shim/include/shim_utils.h @@ -5,14 +5,21 @@ #pragma once +#include +#include +#include +#include +#include +#include + OPENTELEMETRY_BEGIN_NAMESPACE -namespace opentracingshim::shimutils +namespace opentracingshim::utils { - -using opentelemetry::common::AttributeValue; -static inline AttributeValue attributeFromValue(const opentracing::Value& value) +static inline opentelemetry::common::AttributeValue attributeFromValue(const opentracing::Value& value) { + using opentelemetry::common::AttributeValue; + static struct { AttributeValue operator()(bool v) { return v; } @@ -21,12 +28,12 @@ static inline AttributeValue attributeFromValue(const opentracing::Value& value) AttributeValue operator()(uint64_t v) { return v; } AttributeValue operator()(std::string v) { return v.c_str(); } AttributeValue operator()(opentracing::string_view v) { return nostd::string_view{v.data()}; } - AttributeValue operator()(std::nullptr_t) { return std::string{}; } + AttributeValue operator()(std::nullptr_t) { return nostd::string_view{}; } AttributeValue operator()(const char* v) { return v; } - AttributeValue operator()(opentracing::util::recursive_wrapper) { return std::string{}; } - AttributeValue operator()(opentracing::util::recursive_wrapper) { return std::string{}; } + AttributeValue operator()(opentracing::util::recursive_wrapper) { return nostd::string_view{}; } + AttributeValue operator()(opentracing::util::recursive_wrapper) { return nostd::string_view{}; } } AttributeMapper; - + return opentracing::Value::visit(value, AttributeMapper); } @@ -54,7 +61,7 @@ class CarrierWriterShim : public opentelemetry::context::propagation::TextMapCar { public: CarrierWriterShim(const T& writer) : writer_(writer) {} - + // returns the value associated with the passed key. virtual nostd::string_view Get(nostd::string_view key) const noexcept override { @@ -76,22 +83,24 @@ class CarrierReaderShim : public opentelemetry::context::propagation::TextMapCar { public: CarrierReaderShim(const T& reader) : reader_(reader) {} - + // returns the value associated with the passed key. virtual nostd::string_view Get(nostd::string_view key) const noexcept override { - // First try carrier.LookupKey since that can potentially be the fastest approach. - auto result = reader_.LookupKey(key.data()); + nostd::string_view value; - if (!result.has_value() || - opentracing::are_errors_equal(result.error(), opentracing::lookup_key_not_supported_error)) + // First try carrier.LookupKey since that can potentially be the fastest approach. + if (auto result = reader_.LookupKey(key.data())) + { + value = result.value().data(); + } + else // Fall back to iterating through all of the keys. { - // Fall back to iterating through all of the keys. - reader_.ForeachKey([key, &result] + reader_.ForeachKey([key, &value] (opentracing::string_view k, opentracing::string_view v) -> opentracing::expected { - if (key == k) + if (k == key.data()) { - result = opentracing::make_expected(v); + value = v.data(); // Found key, so bail out of the loop with a success error code. return opentracing::make_unexpected(std::error_code{}); } @@ -99,7 +108,7 @@ class CarrierReaderShim : public opentelemetry::context::propagation::TextMapCar }); } - return nostd::string_view{ result.has_value() ? result.value().data() : "" }; + return value; } // stores the key-value pair. @@ -111,29 +120,29 @@ class CarrierReaderShim : public opentelemetry::context::propagation::TextMapCar // list of all the keys in the carrier. virtual bool Keys(nostd::function_ref callback) const noexcept override { - reader_.ForeachKey([&callback] - (opentracing::string_view k, opentracing::string_view v) -> opentracing::expected { - callback(k.data()); - return opentracing::make_expected(); - }); - return true; + return reader_.ForeachKey([&callback] + (opentracing::string_view key, opentracing::string_view) -> opentracing::expected { + return callback(key.data()) + ? opentracing::make_expected() + : opentracing::make_unexpected(std::error_code{}); + }).has_value(); } private: const T& reader_; }; -static inline bool isBaggageEmpty(const BaggagePtr& baggage) +static inline bool isBaggageEmpty(const nostd::shared_ptr& baggage) { if (baggage) { return baggage->GetAllEntries([](nostd::string_view, nostd::string_view){ return false; - }); + }); } return true; } -} // namespace opentracingshim::shimutils +} // namespace opentracingshim::utils OPENTELEMETRY_END_NAMESPACE diff --git a/opentracing-shim/include/span_context_shim.h b/opentracing-shim/include/span_context_shim.h index 12d2f57acc..d615d56d0b 100644 --- a/opentracing-shim/include/span_context_shim.h +++ b/opentracing-shim/include/span_context_shim.h @@ -10,7 +10,7 @@ #include "opentracing/span.h" OPENTELEMETRY_BEGIN_NAMESPACE -namespace opentracingshim +namespace opentracingshim { using BaggagePtr = nostd::shared_ptr; @@ -35,4 +35,4 @@ class SpanContextShim final : public opentracing::SpanContext }; } // namespace opentracingshim -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE diff --git a/opentracing-shim/include/span_shim.h b/opentracing-shim/include/span_shim.h index fe341debbf..72b7349c89 100644 --- a/opentracing-shim/include/span_shim.h +++ b/opentracing-shim/include/span_shim.h @@ -15,7 +15,7 @@ #include "opentracing/span.h" OPENTELEMETRY_BEGIN_NAMESPACE -namespace opentracingshim +namespace opentracingshim { using SpanPtr = nostd::shared_ptr; @@ -49,4 +49,4 @@ class SpanShim : public opentracing::Span }; } // namespace opentracingshim -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE diff --git a/opentracing-shim/include/tracer_shim.h b/opentracing-shim/include/tracer_shim.h index e91b8a2b03..0726b12f5a 100644 --- a/opentracing-shim/include/tracer_shim.h +++ b/opentracing-shim/include/tracer_shim.h @@ -11,7 +11,7 @@ #include "opentracing/tracer.h" OPENTELEMETRY_BEGIN_NAMESPACE -namespace opentracingshim +namespace opentracingshim { using TracerPtr = nostd::shared_ptr; @@ -19,54 +19,29 @@ using TracerProviderPtr = nostd::shared_ptr; struct OpenTracingPropagators { - PropagatorPtr text_map; - PropagatorPtr http_headers; + PropagatorPtr text_map; + PropagatorPtr http_headers; }; class TracerShim : public opentracing::Tracer { public: - /** - * Creates a {@code opentracing::Tracer} shim out of - * {@code Provider::GetTracerProvider()} and - * {@code GlobalTextMapPropagator::GetGlobalPropagator()}. - * - * @returns a {@code opentracing::Tracer}. - */ - static inline std::shared_ptr createTracerShim() noexcept + // This operation MUST accept the following parameters: + // - An OpenTelemetry TracerProvider. This operation MUST use this TracerProvider to obtain a + // Tracer with the name opentracing-shim along with the current shim library version. + // - OpenTelemetry Propagators to be used to perform injection and extraction for the the + // OpenTracing TextMap and HTTPHeaders formats. If not specified, no Propagator values will + // be stored in the Shim, and the global OpenTelemetry TextMap propagator will be used for + // both OpenTracing TextMap and HTTPHeaders formats. + static inline std::shared_ptr createTracerShim( + const TracerProviderPtr& provider = opentelemetry::trace::Provider::GetTracerProvider(), + const OpenTracingPropagators& propagators = {}) noexcept { - return createTracerShim(opentelemetry::trace::Provider::GetTracerProvider()); - } - - /** - * Creates a {@code opentracing::Tracer} shim using the provided - * {@code TracerProvider} and - * {@code TextMapPropagator} instance. - * - * @param provider the {@code TracerProvider} instance used to create this shim. - * @param propagators the {@code OpenTracingPropagators} instance used to create this shim. - * @returns a {@code opentracing::Tracer}. - */ - static inline std::shared_ptr createTracerShim(const TracerProviderPtr& provider, - const OpenTracingPropagators& propagators = {}) noexcept - { - return createTracerShim(provider->GetTracer("opentracing-shim"), propagators); - } - - /** - * Creates a {@code opentracing::Tracer} shim using provided - * {@code Tracer} instance and - * {@code GlobalTextMapPropagator::GetGlobalPropagator()}. - * - * @returns a {@code opentracing::Tracer}. - */ - static inline std::shared_ptr createTracerShim(const TracerPtr& tracer, - const OpenTracingPropagators& propagators = {}) noexcept - { - return std::shared_ptr(new (std::nothrow) TracerShim(tracer, propagators)); + return std::shared_ptr( + new (std::nothrow) TracerShim(provider->GetTracer("opentracing-shim"), propagators)); } // Overrides - std::unique_ptr StartSpanWithOptions(opentracing::string_view operation_name, + std::unique_ptr StartSpanWithOptions(opentracing::string_view operation_name, const opentracing::StartSpanOptions& options) const noexcept override; opentracing::expected Inject(const opentracing::SpanContext& sc, std::ostream& writer) const override; @@ -83,11 +58,11 @@ class TracerShim : public opentracing::Tracer explicit TracerShim(const TracerPtr& tracer, const OpenTracingPropagators& propagators) : tracer_(tracer), propagators_(propagators) {} template - opentracing::expected injectImpl(const opentracing::SpanContext& sc, - const T& writer, + opentracing::expected injectImpl(const opentracing::SpanContext& sc, + const T& writer, const PropagatorPtr& propagator) const; template - opentracing::expected> extractImpl(const T& reader, + opentracing::expected> extractImpl(const T& reader, const PropagatorPtr& propagator) const; TracerPtr tracer_; @@ -96,4 +71,4 @@ class TracerShim : public opentracing::Tracer }; } // namespace opentracingshim -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE diff --git a/opentracing-shim/src/span_shim.cc b/opentracing-shim/src/span_shim.cc index 7ba644215b..fedd3575cf 100644 --- a/opentracing-shim/src/span_shim.cc +++ b/opentracing-shim/src/span_shim.cc @@ -24,7 +24,7 @@ void SpanShim::handleError(const opentracing::Value& value) noexcept // - false maps to Ok // - no value being set maps to Unset. auto code = StatusCode::kUnset; - const auto& str_value = shimutils::stringFromValue(value); + const auto& str_value = utils::stringFromValue(value); if (str_value == "true") { @@ -59,7 +59,7 @@ void SpanShim::SetTag(opentracing::string_view key, const opentracing::Value& va } else { - span_->SetAttribute(key.data(), shimutils::attributeFromValue(value)); + span_->SetAttribute(key.data(), utils::attributeFromValue(value)); } } @@ -106,7 +106,7 @@ void SpanShim::logImpl(opentracing::SystemTime timestamp, nostd::spansecond) : std::string{"log"}; + auto name = (event != fields.end()) ? utils::stringFromValue(event->second) : std::string{"log"}; // If pair set contains an event=error entry, the values MUST be mapped to an Event // with the conventions outlined in the Exception semantic conventions document: bool is_error = (name == opentracing::ext::error); @@ -119,7 +119,7 @@ void SpanShim::logImpl(opentracing::SystemTime timestamp, nostd::span baggage_items; - // If a list of Span references is specified... for (const auto& entry : options.references) { @@ -111,7 +109,6 @@ static BaggagePtr makeBaggage(const opentracing::StartSpanOptions& options) noex }); } } - // If no such lisf of references is specified, the current Baggage // MUST be used as the initial value of the newly created Span. return baggage_items.empty() @@ -128,7 +125,7 @@ static std::vector> makeTags(cons // be set at the creation time of the OpenTelemetry Span. for (const auto& entry : options.tags) { - tags.emplace_back(entry.first, shimutils::attributeFromValue(entry.second)); + tags.emplace_back(entry.first, utils::attributeFromValue(entry.second)); } return tags; @@ -145,7 +142,6 @@ std::unique_ptr TracerShim::StartSpanWithOptions(opentracing: const auto& links = detail::makeReferenceLinks(options); const auto& baggage = detail::makeBaggage(options); const auto& attributes = detail::makeTags(options); - auto span = tracer_->StartSpan(operation_name.data(), attributes, links, opts); auto span_shim = new SpanShim(*this, span, baggage); @@ -237,7 +233,7 @@ opentracing::expected TracerShim::injectImpl(const opentracing::SpanContex // It MUST inject any non-empty Baggage even amidst no valid SpanContext. const auto& context = opentelemetry::baggage::SetBaggage(current_context, context_shim->baggage()); - shimutils::CarrierWriterShim carrier{writer}; + utils::CarrierWriterShim carrier{writer}; propagator->Inject(carrier, context); } @@ -250,7 +246,7 @@ opentracing::expected> TracerShim::ext { // Extract the underlying OpenTelemetry Span and Baggage using either the explicitly registered // or the global OpenTelemetry Propagators, as configured at construction time. - shimutils::CarrierReaderShim carrier{reader}; + utils::CarrierReaderShim carrier{reader}; auto current_context = opentelemetry::context::RuntimeContext::GetCurrent(); auto context = propagator->Extract(carrier, current_context); auto span_context = opentelemetry::trace::GetSpan(context)->GetContext(); @@ -259,7 +255,7 @@ opentracing::expected> TracerShim::ext // If the extracted SpanContext is invalid AND the extracted Baggage is empty, // this operation MUST return a null value, and otherwise it MUST return a // SpanContext Shim instance with the extracted values. - SpanContextShim* context_shim = (!span_context.IsValid() && shimutils::isBaggageEmpty(baggage)) + SpanContextShim* context_shim = (!span_context.IsValid() && utils::isBaggageEmpty(baggage)) ? nullptr : new SpanContextShim(span_context, baggage); diff --git a/opentracing-shim/test/shim_mocks.h b/opentracing-shim/test/shim_mocks.h new file mode 100644 index 0000000000..2842c35db0 --- /dev/null +++ b/opentracing-shim/test/shim_mocks.h @@ -0,0 +1,111 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include + +namespace baggage = opentelemetry::baggage; +namespace context = opentelemetry::context; +namespace nostd = opentelemetry::nostd; + +struct MockPropagator : public context::propagation::TextMapPropagator +{ + // Returns the context that is stored in the carrier with the TextMapCarrier as extractor. + context::Context Extract(const context::propagation::TextMapCarrier &carrier, + context::Context &context) noexcept override + { + std::vector> kvs; + carrier.Keys([&carrier,&kvs](nostd::string_view k){ + kvs.emplace_back(k, carrier.Get(k)); + return true; + }); + is_extracted = true; + return baggage::SetBaggage(context, nostd::shared_ptr(new baggage::Baggage(kvs))); + } + + // Sets the context for carrier with self defined rules. + void Inject(context::propagation::TextMapCarrier &carrier, + const context::Context &context) noexcept override + { + auto baggage = baggage::GetBaggage(context); + baggage->GetAllEntries([&carrier](nostd::string_view k, nostd::string_view v){ + carrier.Set(k, v); + return true; + }); + is_injected = true; + } + + // Gets the fields set in the carrier by the `inject` method + bool Fields(nostd::function_ref callback) const noexcept override + { + return true; + } + + bool is_extracted = false; + bool is_injected = false; +}; + +struct TextMapCarrier : opentracing::TextMapReader, opentracing::TextMapWriter { + TextMapCarrier(std::unordered_map& text_map_) + : text_map(text_map_) {} + + opentracing::expected Set(opentracing::string_view key, opentracing::string_view value) const override { + text_map[key] = value; + return {}; + } + + opentracing::expected LookupKey(opentracing::string_view key) const override { + if (!supports_lookup) { + return opentracing::make_unexpected(opentracing::lookup_key_not_supported_error); + } + auto iter = text_map.find(key); + if (iter != text_map.end()) { + return opentracing::string_view{iter->second}; + } else { + return opentracing::make_unexpected(opentracing::key_not_found_error); + } + } + + opentracing::expected ForeachKey( + std::function(opentracing::string_view key, opentracing::string_view value)> f) + const override { + ++foreach_key_call_count; + for (const auto& key_value : text_map) { + auto result = f(key_value.first, key_value.second); + if (!result) return result; + } + return {}; + } + + bool supports_lookup = false; + mutable int foreach_key_call_count = 0; + std::unordered_map& text_map; +}; + +struct HTTPHeadersCarrier : opentracing::HTTPHeadersReader, opentracing::HTTPHeadersWriter { + HTTPHeadersCarrier(std::unordered_map& text_map_) + : text_map(text_map_) {} + + opentracing::expected Set(opentracing::string_view key, opentracing::string_view value) const override { + text_map[key] = value; + return {}; + } + + opentracing::expected ForeachKey( + std::function(opentracing::string_view key, opentracing::string_view value)> f) + const override { + for (const auto& key_value : text_map) { + auto result = f(key_value.first, key_value.second); + if (!result) return result; + } + return {}; + } + + std::unordered_map& text_map; +}; diff --git a/opentracing-shim/test/shim_utils_test.cc b/opentracing-shim/test/shim_utils_test.cc new file mode 100644 index 0000000000..665f070b9c --- /dev/null +++ b/opentracing-shim/test/shim_utils_test.cc @@ -0,0 +1,196 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "shim_utils.h" +#include "shim_mocks.h" + +#include + +namespace baggage = opentelemetry::baggage; +namespace common = opentelemetry::common; +namespace nostd = opentelemetry::nostd; +namespace shim = opentelemetry::opentracingshim; + +class ShimUtilsTest : public testing::Test +{ +protected: + virtual void SetUp() + { + } + + virtual void TearDown() + { + } +}; + +TEST_F(ShimUtilsTest, IsBaggageEmpty) +{ + auto none = nostd::shared_ptr(nullptr); + ASSERT_TRUE(shim::utils::isBaggageEmpty(none)); + + auto empty = nostd::shared_ptr(new baggage::Baggage({})); + ASSERT_TRUE(shim::utils::isBaggageEmpty(empty)); + + std::map list{{ "foo", "bar" }}; + auto non_empty = nostd::shared_ptr(new baggage::Baggage(list)); + ASSERT_FALSE(shim::utils::isBaggageEmpty(non_empty)); +} + +TEST_F(ShimUtilsTest, StringFromValue) +{ + ASSERT_EQ(shim::utils::stringFromValue(true), "true"); + ASSERT_EQ(shim::utils::stringFromValue(false), "false"); + ASSERT_EQ(shim::utils::stringFromValue(1234.567890), "1234.567890"); + ASSERT_EQ(shim::utils::stringFromValue(42l), "42"); + ASSERT_EQ(shim::utils::stringFromValue(55ul), "55"); + ASSERT_EQ(shim::utils::stringFromValue(std::string{"a string"}), "a string"); + ASSERT_EQ(shim::utils::stringFromValue(opentracing::string_view{"a string view"}), "a string view"); + ASSERT_EQ(shim::utils::stringFromValue(nullptr), ""); + ASSERT_EQ(shim::utils::stringFromValue("a char ptr"), "a char ptr"); + + opentracing::util::recursive_wrapper values{}; + ASSERT_EQ(shim::utils::stringFromValue(values.get()), ""); + + opentracing::util::recursive_wrapper dict{}; + ASSERT_EQ(shim::utils::stringFromValue(dict.get()), ""); +} + +TEST_F(ShimUtilsTest, AttributeFromValue) +{ + auto value = shim::utils::attributeFromValue(true); + ASSERT_EQ(value.index(), common::AttributeType::kTypeBool); + ASSERT_TRUE(nostd::get(value)); + + value = shim::utils::attributeFromValue(false); + ASSERT_EQ(value.index(), common::AttributeType::kTypeBool); + ASSERT_FALSE(nostd::get(value)); + + value = shim::utils::attributeFromValue(1234.567890); + ASSERT_EQ(value.index(), common::AttributeType::kTypeDouble); + ASSERT_EQ(nostd::get(value), 1234.567890); + + value = shim::utils::attributeFromValue(42l); + ASSERT_EQ(value.index(), common::AttributeType::kTypeInt64); + ASSERT_EQ(nostd::get(value), 42l); + + value = shim::utils::attributeFromValue(55ul); + ASSERT_EQ(value.index(), common::AttributeType::kTypeUInt64); + ASSERT_EQ(nostd::get(value), 55ul); + + value = shim::utils::attributeFromValue(std::string{"a string"}); + ASSERT_EQ(value.index(), common::AttributeType::kTypeCString); + ASSERT_STREQ(nostd::get(value), "a string"); + + value = shim::utils::attributeFromValue(opentracing::string_view{"a string view"}); + ASSERT_EQ(value.index(), common::AttributeType::kTypeString); + ASSERT_EQ(nostd::get(value), nostd::string_view{"a string view"}); + + value = shim::utils::attributeFromValue(nullptr); + ASSERT_EQ(value.index(), common::AttributeType::kTypeString); + ASSERT_EQ(nostd::get(value), nostd::string_view{}); + + value = shim::utils::attributeFromValue("a char ptr"); + ASSERT_EQ(value.index(), common::AttributeType::kTypeCString); + ASSERT_STREQ(nostd::get(value), "a char ptr"); + + opentracing::util::recursive_wrapper values{}; + value = shim::utils::attributeFromValue(values.get()); + ASSERT_EQ(value.index(), common::AttributeType::kTypeString); + ASSERT_EQ(nostd::get(value), nostd::string_view{}); + + opentracing::util::recursive_wrapper dict{}; + value = shim::utils::attributeFromValue(dict.get()); + ASSERT_EQ(value.index(), common::AttributeType::kTypeString); + ASSERT_EQ(nostd::get(value), nostd::string_view{}); +} + +TEST_F(ShimUtilsTest, TextMapReader_Get_LookupKey_Unsupported) +{ + std::unordered_map text_map; + TextMapCarrier testee{text_map}; + ASSERT_FALSE(testee.supports_lookup); + ASSERT_EQ(testee.foreach_key_call_count, 0); + + shim::utils::CarrierReaderShim tester{testee}; + auto lookup_unsupported = testee.LookupKey("foo"); + ASSERT_TRUE(text_map.empty()); + ASSERT_TRUE(opentracing::are_errors_equal(lookup_unsupported.error(), opentracing::lookup_key_not_supported_error)); + ASSERT_EQ(tester.Get("foo"), nostd::string_view{}); + ASSERT_EQ(testee.foreach_key_call_count, 1); + + text_map["foo"] = "bar"; + auto lookup_found = testee.LookupKey("foo"); + ASSERT_FALSE(text_map.empty()); + ASSERT_TRUE(opentracing::are_errors_equal(lookup_unsupported.error(), opentracing::lookup_key_not_supported_error)); + ASSERT_EQ(tester.Get("foo"), nostd::string_view{"bar"}); + ASSERT_EQ(testee.foreach_key_call_count, 2); +} + +TEST_F(ShimUtilsTest, TextMapReader_Get_LookupKey_Supported) +{ + std::unordered_map text_map; + TextMapCarrier testee{text_map}; + testee.supports_lookup = true; + ASSERT_TRUE(testee.supports_lookup); + ASSERT_EQ(testee.foreach_key_call_count, 0); + + shim::utils::CarrierReaderShim tester{testee}; + auto lookup_not_found = testee.LookupKey("foo"); + ASSERT_TRUE(text_map.empty()); + ASSERT_TRUE(opentracing::are_errors_equal(lookup_not_found.error(), opentracing::key_not_found_error)); + ASSERT_EQ(tester.Get("foo"), nostd::string_view{}); + ASSERT_EQ(testee.foreach_key_call_count, 1); + + text_map["foo"] = "bar"; + auto lookup_found = testee.LookupKey("foo"); + ASSERT_FALSE(text_map.empty()); + ASSERT_EQ(lookup_found.value(), opentracing::string_view{"bar"}); + ASSERT_EQ(tester.Get("foo"), nostd::string_view{"bar"}); + ASSERT_EQ(testee.foreach_key_call_count, 1); +} + +TEST_F(ShimUtilsTest, TextMapReader_Keys) +{ + std::unordered_map text_map; + TextMapCarrier testee{text_map}; + ASSERT_EQ(testee.foreach_key_call_count, 0); + + shim::utils::CarrierReaderShim tester{testee}; + std::vector kvs; + auto callback = [&text_map,&kvs](nostd::string_view k){ + kvs.emplace_back(k); + return !text_map.empty(); + }; + + ASSERT_TRUE(tester.Keys(callback)); + ASSERT_TRUE(text_map.empty()); + ASSERT_TRUE(kvs.empty()); + ASSERT_EQ(testee.foreach_key_call_count, 1); + + text_map["foo"] = "bar"; + text_map["bar"] = "baz"; + text_map["baz"] = "foo"; + ASSERT_TRUE(tester.Keys(callback)); + ASSERT_FALSE(text_map.empty()); + ASSERT_EQ(text_map.size(), kvs.size()); + ASSERT_EQ(testee.foreach_key_call_count, 2); +} + +TEST_F(ShimUtilsTest, TextMapWriter_Set) +{ + std::unordered_map text_map; + TextMapCarrier testee{text_map}; + shim::utils::CarrierWriterShim tester{testee}; + ASSERT_TRUE(text_map.empty()); + + tester.Set("foo", "bar"); + tester.Set("bar", "baz"); + tester.Set("baz", "foo"); + ASSERT_FALSE(text_map.empty()); + ASSERT_EQ(text_map.size(), 3); + ASSERT_EQ(text_map["foo"], "bar"); + ASSERT_EQ(text_map["bar"], "baz"); + ASSERT_EQ(text_map["baz"], "foo"); +} \ No newline at end of file diff --git a/opentracing-shim/test/tracer_shim_test.cc b/opentracing-shim/test/tracer_shim_test.cc index c4c2aa7937..3e0abd77f6 100644 --- a/opentracing-shim/test/tracer_shim_test.cc +++ b/opentracing-shim/test/tracer_shim_test.cc @@ -1,10 +1,14 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ #include "tracer_shim.h" +#include "span_shim.h" #include "span_context_shim.h" +#include "shim_utils.h" +#include "shim_mocks.h" -#include #include #include @@ -15,102 +19,6 @@ namespace context = opentelemetry::context; namespace baggage = opentelemetry::baggage; namespace shim = opentelemetry::opentracingshim; -struct MockPropagator : public context::propagation::TextMapPropagator -{ - // Returns the context that is stored in the carrier with the TextMapCarrier as extractor. - context::Context Extract(const context::propagation::TextMapCarrier &carrier, - context::Context &context) noexcept override - { - std::vector> kvs; - carrier.Keys([&carrier,&kvs](nostd::string_view k){ - kvs.emplace_back(k, carrier.Get(k)); - return true; - }); - is_extracted = true; - return baggage::SetBaggage(context, nostd::shared_ptr(new baggage::Baggage(kvs))); - } - - // Sets the context for carrier with self defined rules. - void Inject(context::propagation::TextMapCarrier &carrier, - const context::Context &context) noexcept override - { - auto baggage = baggage::GetBaggage(context); - baggage->GetAllEntries([&carrier](nostd::string_view k, nostd::string_view v){ - carrier.Set(k, v); - return true; - }); - is_injected = true; - } - - // Gets the fields set in the carrier by the `inject` method - bool Fields(nostd::function_ref callback) const noexcept override - { - return true; - } - - bool is_extracted = false; - bool is_injected = false; -}; - -struct TextMapCarrier : opentracing::TextMapReader, opentracing::TextMapWriter { - TextMapCarrier(std::unordered_map& text_map_) - : text_map(text_map_) {} - - opentracing::expected Set(opentracing::string_view key, opentracing::string_view value) const override { - text_map[key] = value; - return {}; - } - - opentracing::expected LookupKey(opentracing::string_view key) const override { - if (!supports_lookup) { - return opentracing::make_unexpected(opentracing::lookup_key_not_supported_error); - } - auto iter = text_map.find(key); - if (iter != text_map.end()) { - return opentracing::string_view{iter->second}; - } else { - return opentracing::make_unexpected(opentracing::key_not_found_error); - } - } - - opentracing::expected ForeachKey( - std::function(opentracing::string_view key, opentracing::string_view value)> f) - const override { - ++foreach_key_call_count; - for (const auto& key_value : text_map) { - auto result = f(key_value.first, key_value.second); - if (!result) return result; - } - return {}; - } - - bool supports_lookup = false; - mutable int foreach_key_call_count = 0; - std::unordered_map& text_map; -}; - -struct HTTPHeadersCarrier : opentracing::HTTPHeadersReader, opentracing::HTTPHeadersWriter { - HTTPHeadersCarrier(std::unordered_map& text_map_) - : text_map(text_map_) {} - - opentracing::expected Set(opentracing::string_view key, opentracing::string_view value) const override { - text_map[key] = value; - return {}; - } - - opentracing::expected ForeachKey( - std::function(opentracing::string_view key, opentracing::string_view value)> f) - const override { - for (const auto& key_value : text_map) { - auto result = f(key_value.first, key_value.second); - if (!result) return result; - } - return {}; - } - - std::unordered_map& text_map; -}; - class TracerShimTest : public testing::Test { public: @@ -126,9 +34,10 @@ class TracerShimTest : public testing::Test text_map_format = new MockPropagator(); http_headers_format = new MockPropagator(); - tracer_shim = shim::TracerShim::createTracerShim(trace_api::Provider::GetTracerProvider(), - { .text_map = nostd::shared_ptr(text_map_format), - .http_headers = nostd::shared_ptr(http_headers_format) }); + tracer_shim = shim::TracerShim::createTracerShim(trace_api::Provider::GetTracerProvider(), { + .text_map = nostd::shared_ptr(text_map_format), + .http_headers = nostd::shared_ptr(http_headers_format) + }); } virtual void TearDown() @@ -151,6 +60,13 @@ TEST_F(TracerShimTest, TracerGloballyRegistered) ASSERT_TRUE(opentracing::Tracer::IsGlobalTracerRegistered()); } +TEST_F(TracerShimTest, Close) +{ + tracer_shim->Close(); + auto span_shim = tracer_shim->StartSpan("a"); + ASSERT_TRUE(span_shim == nullptr); +} + TEST_F(TracerShimTest, InjectInvalidCarrier) { auto span_shim = tracer_shim->StartSpan("a"); @@ -234,20 +150,18 @@ TEST_F(TracerShimTest, ExtractOnlyBaggage) std::unordered_map text_map; auto span_shim = tracer_shim->StartSpan("a"); span_shim->SetBaggageItem("foo", "bar"); - ASSERT_EQ(span_shim->BaggageItem("foo"), "bar"); - TextMapCarrier carrier{text_map}; - tracer_shim->Inject(span_shim->context(), carrier); - - auto span_context = tracer_shim->Extract(carrier); + tracer_shim->Inject(span_shim->context(), TextMapCarrier{text_map}); + auto span_context = tracer_shim->Extract(TextMapCarrier{text_map}); ASSERT_TRUE(span_context.value() != nullptr); - // auto span_context_shim = dynamic_cast(span_context.value().get()); - // ASSERT_TRUE(span_context_shim != nullptr); - // ASSERT_TRUE(span_context_shim->context().IsValid()); + auto span_context_shim = dynamic_cast(span_context.value().get()); + ASSERT_TRUE(span_context_shim != nullptr); + ASSERT_FALSE(span_context_shim->context().IsValid()); + ASSERT_FALSE(shim::utils::isBaggageEmpty(span_context_shim->baggage())); - // std::string value; - // ASSERT_TRUE(span_context_shim->BaggageItem("foo", value)); - // ASSERT_EQ(value, "bar"); + std::string value; + ASSERT_TRUE(span_context_shim->BaggageItem("foo", value)); + ASSERT_EQ(value, "bar"); }