From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- .../opentelemetry-cpp/api/test/CMakeLists.txt | 15 ++ .../opentelemetry-cpp/api/test/_metrics/BUILD | 50 +++++ .../api/test/_metrics/CMakeLists.txt | 9 + .../api/test/_metrics/meter_provider_test.cc | 45 ++++ .../api/test/_metrics/noop_instrument_test.cc | 191 +++++++++++++++++ .../api/test/_metrics/noop_metrics_test.cc | 83 ++++++++ .../opentelemetry-cpp/api/test/baggage/BUILD | 26 +++ .../api/test/baggage/CMakeLists.txt | 15 ++ .../api/test/baggage/baggage_benchmark.cc | 117 ++++++++++ .../api/test/baggage/baggage_test.cc | 218 +++++++++++++++++++ .../api/test/baggage/propagation/BUILD | 16 ++ .../api/test/baggage/propagation/CMakeLists.txt | 9 + .../baggage/propagation/baggage_propagator_test.cc | 113 ++++++++++ .../opentelemetry-cpp/api/test/common/BUILD | 41 ++++ .../api/test/common/CMakeLists.txt | 15 ++ .../api/test/common/kv_properties_test.cc | 235 +++++++++++++++++++++ .../api/test/common/spinlock_benchmark.cc | 152 +++++++++++++ .../api/test/common/string_util_test.cc | 47 +++++ .../opentelemetry-cpp/api/test/context/BUILD | 31 +++ .../api/test/context/CMakeLists.txt | 13 ++ .../api/test/context/context_test.cc | 147 +++++++++++++ .../api/test/context/propagation/BUILD | 16 ++ .../api/test/context/propagation/CMakeLists.txt | 9 + .../propagation/composite_propagator_test.cc | 124 +++++++++++ .../api/test/context/runtime_context_test.cc | 135 ++++++++++++ .../opentelemetry-cpp/api/test/core/BUILD | 14 ++ .../opentelemetry-cpp/api/test/core/CMakeLists.txt | 9 + .../api/test/core/timestamp_test.cc | 67 ++++++ .../opentelemetry-cpp/api/test/logs/BUILD | 33 +++ .../opentelemetry-cpp/api/test/logs/CMakeLists.txt | 9 + .../opentelemetry-cpp/api/test/logs/logger_test.cc | 165 +++++++++++++++ .../api/test/logs/provider_test.cc | 77 +++++++ .../opentelemetry-cpp/api/test/metrics/BUILD | 31 +++ .../api/test/metrics/CMakeLists.txt | 9 + .../api/test/metrics/meter_provider_test.cc | 38 ++++ .../api/test/metrics/noop_sync_instrument_test.cc | 50 +++++ .../opentelemetry-cpp/api/test/nostd/BUILD | 104 +++++++++ .../api/test/nostd/CMakeLists.txt | 19 ++ .../api/test/nostd/function_ref_test.cc | 36 ++++ .../api/test/nostd/shared_ptr_test.cc | 189 +++++++++++++++++ .../opentelemetry-cpp/api/test/nostd/span_test.cc | 191 +++++++++++++++++ .../api/test/nostd/string_view_test.cc | 125 +++++++++++ .../api/test/nostd/unique_ptr_test.cc | 169 +++++++++++++++ .../api/test/nostd/utility_test.cc | 56 +++++ .../api/test/nostd/variant_test.cc | 119 +++++++++++ .../opentelemetry-cpp/api/test/plugin/BUILD | 17 ++ .../api/test/plugin/CMakeLists.txt | 10 + .../api/test/plugin/dynamic_load_test.cc | 14 ++ .../opentelemetry-cpp/api/test/trace/BUILD | 199 +++++++++++++++++ .../api/test/trace/CMakeLists.txt | 29 +++ .../api/test/trace/default_span_test.cc | 24 +++ .../api/test/trace/key_value_iterable_view_test.cc | 68 ++++++ .../opentelemetry-cpp/api/test/trace/noop_test.cc | 81 +++++++ .../api/test/trace/propagation/BUILD | 52 +++++ .../api/test/trace/propagation/CMakeLists.txt | 10 + .../test/trace/propagation/b3_propagation_test.cc | 189 +++++++++++++++++ .../trace/propagation/http_text_format_test.cc | 211 ++++++++++++++++++ .../trace/propagation/jaeger_propagation_test.cc | 168 +++++++++++++++ .../api/test/trace/propagation/util.h | 14 ++ .../api/test/trace/provider_test.cc | 36 ++++ .../opentelemetry-cpp/api/test/trace/scope_test.cc | 51 +++++ .../api/test/trace/span_benchmark.cc | 129 +++++++++++ .../api/test/trace/span_context_test.cc | 55 +++++ .../api/test/trace/span_id_benchmark.cc | 55 +++++ .../api/test/trace/span_id_test.cc | 58 +++++ .../api/test/trace/trace_flags_test.cc | 43 ++++ .../api/test/trace/trace_id_test.cc | 58 +++++ .../api/test/trace/trace_state_test.cc | 196 +++++++++++++++++ .../api/test/trace/tracer_test.cc | 39 ++++ 69 files changed, 5188 insertions(+) create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/_metrics/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/_metrics/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/_metrics/meter_provider_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_instrument_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_metrics_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/baggage/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/baggage/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_benchmark.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/baggage_propagator_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/common/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/common/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/common/kv_properties_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/common/spinlock_benchmark.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/common/string_util_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/context/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/context/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/context/context_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/context/propagation/composite_propagator_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/context/runtime_context_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/core/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/core/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/core/timestamp_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/logs/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/logs/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/logs/logger_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/logs/provider_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/metrics/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/metrics/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/metrics/meter_provider_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/metrics/noop_sync_instrument_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/function_ref_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/shared_ptr_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/span_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/string_view_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/unique_ptr_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/utility_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/nostd/variant_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/plugin/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/plugin/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/plugin/dynamic_load_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/default_span_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/key_value_iterable_view_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/noop_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/BUILD create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/CMakeLists.txt create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/b3_propagation_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/http_text_format_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/jaeger_propagation_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/propagation/util.h create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/provider_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/scope_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/span_benchmark.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/span_context_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_benchmark.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/span_id_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_flags_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_id_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/trace_state_test.cc create mode 100644 src/jaegertracing/opentelemetry-cpp/api/test/trace/tracer_test.cc (limited to 'src/jaegertracing/opentelemetry-cpp/api/test') diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/CMakeLists.txt new file mode 100644 index 000000000..41125005e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/CMakeLists.txt @@ -0,0 +1,15 @@ +add_subdirectory(core) +add_subdirectory(context) +add_subdirectory(plugin) +add_subdirectory(nostd) +add_subdirectory(trace) +if(WITH_METRICS_PREVIEW) + add_subdirectory(_metrics) +else() + add_subdirectory(metrics) +endif() +if(WITH_LOGS_PREVIEW) + add_subdirectory(logs) +endif() +add_subdirectory(common) +add_subdirectory(baggage) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/BUILD new file mode 100644 index 000000000..6e5b9009b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/BUILD @@ -0,0 +1,50 @@ +load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") + +cc_test( + name = "meter_provider_test", + srcs = [ + "meter_provider_test.cc", + ], + tags = [ + "api", + "metrics", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "noop_metrics_test", + srcs = [ + "noop_metrics_test.cc", + ], + tags = [ + "api", + "metrics", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "noop_instrument_test", + srcs = [ + "noop_instrument_test.cc", + ], + linkstatic = 1, + tags = [ + "api", + "metrics", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/CMakeLists.txt new file mode 100644 index 000000000..9d70c376e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/CMakeLists.txt @@ -0,0 +1,9 @@ +foreach(testname noop_instrument_test meter_provider_test noop_metrics_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 metrics. + TEST_LIST ${testname}) +endforeach() diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/meter_provider_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/meter_provider_test.cc new file mode 100644 index 000000000..507081067 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/meter_provider_test.cc @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_METRICS_PREVIEW +# include +# include "opentelemetry/_metrics/provider.h" +# include "opentelemetry/nostd/shared_ptr.h" + +using opentelemetry::metrics::Meter; +using opentelemetry::metrics::MeterProvider; +using opentelemetry::metrics::Provider; +namespace nostd = opentelemetry::nostd; + +class TestProvider : public MeterProvider +{ + nostd::shared_ptr GetMeter(nostd::string_view library_name, + nostd::string_view library_version) override + { + return nostd::shared_ptr(nullptr); + } +}; + +TEST(Provider, GetMeterProviderDefault) +{ + auto tf = Provider::GetMeterProvider(); + EXPECT_NE(nullptr, tf); +} + +TEST(Provider, SetMeterProvider) +{ + auto tf = nostd::shared_ptr(new TestProvider()); + Provider::SetMeterProvider(tf); + ASSERT_EQ(tf, Provider::GetMeterProvider()); +} + +TEST(Provider, MultipleMeterProviders) +{ + auto tf = nostd::shared_ptr(new TestProvider()); + Provider::SetMeterProvider(tf); + auto tf2 = nostd::shared_ptr(new TestProvider()); + Provider::SetMeterProvider(tf2); + + ASSERT_NE(Provider::GetMeterProvider(), tf); +} +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_instrument_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_instrument_test.cc new file mode 100644 index 000000000..83d8d3960 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_instrument_test.cc @@ -0,0 +1,191 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_METRICS_PREVIEW +# include +# include +# include +# include + +# include "opentelemetry/_metrics/noop.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ + +void noopIntCallback(ObserverResult result) +{ + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + result.observe(1, labelkv); + result.observe(-1, labelkv); +} + +void noopDoubleCallback(ObserverResult result) +{ + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + result.observe(1.5, labelkv); + result.observe(-1.5, labelkv); +} + +TEST(ValueObserver, Observe) +{ + NoopValueObserver alpha("test", "none", "unitless", true, &noopIntCallback); + + NoopValueObserver beta("test", "none", "unitless", true, &noopDoubleCallback); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.observe(1, labelkv); + beta.observe(1.5, labelkv); +} + +TEST(SumObserver, DefaultConstruction) +{ + NoopSumObserver alpha("test", "none", "unitless", true, &noopIntCallback); + + NoopSumObserver beta("test", "none", "unitless", true, &noopDoubleCallback); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.observe(1, labelkv); + beta.observe(1.5, labelkv); +} + +TEST(UpDownSumObserver, DefaultConstruction) +{ + NoopUpDownSumObserver alpha("test", "none", "unitless", true, &noopIntCallback); + + NoopUpDownSumObserver beta("test", "none", "unitless", true, &noopDoubleCallback); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.observe(1, labelkv); + beta.observe(1.0, labelkv); + alpha.observe(-1, labelkv); + beta.observe(-1.0, labelkv); +} + +TEST(Counter, DefaultConstruction) +{ + NoopCounter alpha("test", "none", "unitless", true); + NoopCounter beta("other", "none", "unitless", true); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.bind(labelkv); + + auto gamma = alpha.bindNoopCounter(labelkv); + auto delta = beta.bindNoopCounter(labelkv); + + gamma->unbind(); + delta->unbind(); +} + +TEST(Counter, Add) +{ + NoopCounter alpha("test", "none", "unitless", true); + NoopCounter beta("other", "none", "unitless", true); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.add(1, labelkv); + beta.add(1.5, labelkv); + + auto gamma = alpha.bindNoopCounter(labelkv); + auto delta = beta.bindNoopCounter(labelkv); + + gamma->add(1); + delta->add(1.5); + + gamma->unbind(); + delta->unbind(); +} + +TEST(UpDownCounter, DefaultConstruction) +{ + NoopUpDownCounter alpha("test", "none", "unitless", true); + NoopUpDownCounter beta("other", "none", "unitless", true); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.bind(labelkv); + + auto gamma = alpha.bindNoopUpDownCounter(labelkv); + auto delta = beta.bindNoopUpDownCounter(labelkv); + + gamma->unbind(); + delta->unbind(); +} + +TEST(UpDownCounter, Add) +{ + NoopUpDownCounter alpha("test", "none", "unitless", true); + NoopUpDownCounter beta("other", "none", "unitless", true); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.add(1, labelkv); + beta.add(1.5, labelkv); + + auto gamma = alpha.bindNoopUpDownCounter(labelkv); + auto delta = beta.bindNoopUpDownCounter(labelkv); + + gamma->add(1); + delta->add(1.0); + gamma->add(-1); + delta->add(-1.0); + + gamma->unbind(); + delta->unbind(); +} + +TEST(ValueRecorder, DefaultConstruction) +{ + NoopValueRecorder alpha("test", "none", "unitless", true); + NoopValueRecorder beta("other", "none", "unitless", true); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.bind(labelkv); + + auto gamma = alpha.bindNoopValueRecorder(labelkv); + auto delta = beta.bindNoopValueRecorder(labelkv); + + gamma->unbind(); + delta->unbind(); +} + +TEST(ValueRecorder, Record) +{ + NoopValueRecorder alpha("test", "none", "unitless", true); + NoopValueRecorder beta("other", "none", "unitless", true); + + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + + alpha.record(1, labelkv); + beta.record(1.5, labelkv); + + auto gamma = alpha.bindNoopValueRecorder(labelkv); + auto delta = beta.bindNoopValueRecorder(labelkv); + + gamma->record(1); + delta->record(1.5); + + gamma->unbind(); + delta->unbind(); +} + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_metrics_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_metrics_test.cc new file mode 100644 index 000000000..cc9d1f4b7 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/_metrics/noop_metrics_test.cc @@ -0,0 +1,83 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_METRICS_PREVIEW +# include +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/_metrics/noop.h" +# include "opentelemetry/_metrics/observer_result.h" +# include "opentelemetry/_metrics/sync_instruments.h" + +# include +# include + +OPENTELEMETRY_BEGIN_NAMESPACE + +using opentelemetry::metrics::Meter; +using opentelemetry::metrics::NoopMeter; + +void Callback(opentelemetry::metrics::ObserverResult result) +{ + std::map labels = {{"key", "value"}}; + auto labelkv = common::KeyValueIterableView{labels}; + result.observe(1, labelkv); +} + +TEST(NoopTest, CreateInstruments) +{ + auto m = std::unique_ptr(new NoopMeter{}); + + // Test instrument constructors + m->NewIntCounter("Test counter", "For testing", "Unitless", true); + m->NewIntUpDownCounter("Test ud counter", "For testing", "Unitless", true); + m->NewIntValueRecorder("Test recorder", "For testing", "Unitless", true); + + m->NewIntSumObserver("Test sum obs", "For testing", "Unitless", true, &Callback); + m->NewIntUpDownSumObserver("Test udsum obs", "For testing", "Unitless", true, &Callback); + m->NewIntValueObserver("Test val obs", "For testing", "Unitless", true, &Callback); +} + +TEST(NoopMeter, RecordBatch) +{ + // Test BatchRecord with all supported types + // Create Counter and call RecordBatch for all four supported types: short, int, float, and double + + std::unique_ptr m{std::unique_ptr(new NoopMeter{})}; + + std::map labels = {{"Key", "Value"}}; + auto labelkv = opentelemetry::common::KeyValueIterableView{labels}; + + auto s = m->NewShortCounter("Test short counter", "For testing", "Unitless", true); + + std::array *, 1> siarr{s.get()}; + std::array svarr{1}; + nostd::span *> ssp{siarr}; + nostd::span sval{svarr}; + m->RecordShortBatch(labelkv, ssp, sval); + + auto i = m->NewIntCounter("Test int counter", "For testing", "Unitless", true); + + std::array *, 1> iiarr{i.get()}; + std::array ivarr{1}; + nostd::span *> isp{iiarr}; + nostd::span ival{ivarr}; + m->RecordIntBatch(labelkv, isp, ival); + + auto f = m->NewFloatCounter("Test int counter", "For testing", "Unitless", true); + + std::array *, 1> fiarr{f.get()}; + std::array fvarr{1.0f}; + nostd::span *> fsp{fiarr}; + nostd::span fval{fvarr}; + m->RecordFloatBatch(labelkv, fsp, fval); + + auto d = m->NewDoubleCounter("Test int counter", "For testing", "Unitless", true); + + std::array *, 1> diarr{d.get()}; + std::array dvarr{1.0f}; + nostd::span *> dsp{diarr}; + nostd::span dval{dvarr}; + m->RecordDoubleBatch(labelkv, dsp, dval); +} +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/BUILD new file mode 100644 index 000000000..7c021f46e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/BUILD @@ -0,0 +1,26 @@ +load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") + +cc_test( + name = "baggage_test", + srcs = [ + "baggage_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +otel_cc_benchmark( + name = "baggage_benchmark", + srcs = ["baggage_benchmark.cc"], + tags = [ + "api", + "test", + ], + deps = ["//api"], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/CMakeLists.txt new file mode 100644 index 000000000..0d6cba5a0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/CMakeLists.txt @@ -0,0 +1,15 @@ +include(GoogleTest) + +foreach(testname baggage_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 baggage. + TEST_LIST ${testname}) +endforeach() +add_executable(baggage_benchmark baggage_benchmark.cc) +target_link_libraries(baggage_benchmark benchmark::benchmark + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) +add_subdirectory(propagation) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_benchmark.cc new file mode 100644 index 000000000..9b7529795 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_benchmark.cc @@ -0,0 +1,117 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/baggage/baggage.h" +#include "opentelemetry/nostd/string_view.h" + +#include +#include + +using namespace opentelemetry::baggage; +namespace nostd = opentelemetry::nostd; + +namespace +{ + +const size_t kNumEntries = 10; + +std::string header_with_custom_entries(size_t num_entries) +{ + std::string header; + for (size_t i = 0; i < num_entries; i++) + { + std::string key = "ADecentlyLargekey" + std::to_string(i); + std::string value = "ADecentlyLargeValue" + std::to_string(i); + header += key + "=" + value; + if (i != num_entries - 1) + { + header += ","; + } + } + return header; +} + +void BM_CreateBaggageFromTenEntries(benchmark::State &state) +{ + std::string header = header_with_custom_entries(kNumEntries); + while (state.KeepRunning()) + { + auto baggage = Baggage::FromHeader(header); + } +} +BENCHMARK(BM_CreateBaggageFromTenEntries); + +void BM_ExtractBaggageHavingTenEntries(benchmark::State &state) +{ + auto baggage = Baggage::FromHeader(header_with_custom_entries(kNumEntries)); + while (state.KeepRunning()) + { + baggage->GetAllEntries([](nostd::string_view key, nostd::string_view value) { return true; }); + } +} +BENCHMARK(BM_ExtractBaggageHavingTenEntries); + +void BM_CreateBaggageFrom180Entries(benchmark::State &state) +{ + std::string header = header_with_custom_entries(Baggage::kMaxKeyValuePairs); + while (state.KeepRunning()) + { + auto baggage = Baggage::FromHeader(header); + } +} +BENCHMARK(BM_CreateBaggageFrom180Entries); + +void BM_ExtractBaggageWith180Entries(benchmark::State &state) +{ + auto baggage = Baggage::FromHeader(header_with_custom_entries(Baggage::kMaxKeyValuePairs)); + while (state.KeepRunning()) + { + baggage->GetAllEntries([](nostd::string_view key, nostd::string_view value) { return true; }); + } +} +BENCHMARK(BM_ExtractBaggageWith180Entries); + +void BM_SetValueBaggageWithTenEntries(benchmark::State &state) +{ + auto baggage = Baggage::FromHeader( + header_with_custom_entries(kNumEntries - 1)); // 9 entries, and add one new + while (state.KeepRunning()) + { + auto new_baggage = baggage->Set("new_key", "new_value"); + } +} +BENCHMARK(BM_SetValueBaggageWithTenEntries); + +void BM_SetValueBaggageWith180Entries(benchmark::State &state) +{ + auto baggage = Baggage::FromHeader(header_with_custom_entries( + Baggage::kMaxKeyValuePairs - 1)); // keep 179 entries, and add one new + while (state.KeepRunning()) + { + auto new_baggage = baggage->Set("new_key", "new_value"); + } +} +BENCHMARK(BM_SetValueBaggageWith180Entries); + +void BM_BaggageToHeaderTenEntries(benchmark::State &state) +{ + auto baggage = Baggage::FromHeader(header_with_custom_entries(kNumEntries)); + while (state.KeepRunning()) + { + auto new_baggage = baggage->ToHeader(); + } +} +BENCHMARK(BM_BaggageToHeaderTenEntries); + +void BM_BaggageToHeader180Entries(benchmark::State &state) +{ + auto baggage = Baggage::FromHeader(header_with_custom_entries(Baggage::kMaxKeyValuePairs)); + while (state.KeepRunning()) + { + auto new_baggage = baggage->ToHeader(); + } +} +BENCHMARK(BM_BaggageToHeader180Entries); +} // namespace + +BENCHMARK_MAIN(); diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_test.cc new file mode 100644 index 000000000..9c14fc892 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/baggage_test.cc @@ -0,0 +1,218 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/string_view.h" + +#include +#include +#include + +#include "opentelemetry/baggage/baggage.h" + +using namespace opentelemetry; +using namespace opentelemetry::baggage; + +std::string header_with_custom_entries(size_t num_entries) +{ + std::string header; + for (size_t i = 0; i < num_entries; i++) + { + std::string key = "key" + std::to_string(i); + std::string value = "value" + std::to_string(i); + header += key + "=" + value; + if (i != num_entries - 1) + { + header += ","; + } + } + return header; +} + +std::string header_with_custom_size(size_t key_value_size, size_t num_entries) +{ + std::string header = ""; + for (size_t i = 0; i < num_entries; i++) + { + std::string str = std::to_string(i + 1); + str += "="; + assert(key_value_size > str.size()); + for (size_t j = str.size(); j < key_value_size; j++) + { + str += "a"; + } + + header += str + ','; + } + + header.pop_back(); + return header; +} + +TEST(BaggageTest, ValidateExtractHeader) +{ + auto invalid_key_value_size_header = header_with_custom_size(Baggage::kMaxKeyValueSize + 5, 1); + + struct + { + const char *input; + std::vector keys; + std::vector values; + } testcases[] = { + {"k1=v1", {"k1"}, {"v1"}}, + {"k1=V1,K2=v2;metadata,k3=v3", + {"k1", "K2", "k3"}, + {"V1", "v2;metadata", "v3"}}, // metadata is part of value + {",k1 =v1,k2=v2 ; metadata,", + {"k1", "k2"}, + {"v1", "v2; metadata"}}, // key and value are trimmed + {"1a-2f%40foo=bar%251,a%2A%2Ffoo-_%2Fbar=bar+4", + {"1a-2f@foo", "a*/foo-_/bar"}, + {"bar%1", "bar 4"}}, // decoding is done properly + {"k1=v1,invalidmember,k2=v2", {"k1", "k2"}, {"v1", "v2"}}, // invalid member is skipped + {",", {}, {}}, + {",=,", {}, {}}, + {"", {}, {}}, + {"k1=%5zv", {}, {}}, // invalid hex : invalid second digit + {"k1=%5", {}, {}}, // invalid hex : missing two digits + {"k%z2=v1", {}, {}}, // invalid hex : invalid first digit + {"k%00=v1", {}, {}}, // key not valid + {"k=v%7f", {}, {}}, // value not valid + {invalid_key_value_size_header.data(), {}, {}}}; + for (auto &testcase : testcases) + { + auto baggage = Baggage::FromHeader(testcase.input); + size_t index = 0; + baggage->GetAllEntries([&testcase, &index](nostd::string_view key, nostd::string_view value) { + EXPECT_EQ(key, testcase.keys[index]); + EXPECT_EQ(value, testcase.values[index]); + index++; + return true; + }); + } + + // For header with maximum threshold pairs, no pair is dropped + auto max_pairs_header = header_with_custom_entries(Baggage::kMaxKeyValuePairs); + EXPECT_EQ(Baggage::FromHeader(max_pairs_header.data())->ToHeader(), max_pairs_header.data()); + + // Entries beyond threshold are dropped + auto baggage = Baggage::FromHeader(header_with_custom_entries(Baggage::kMaxKeyValuePairs + 1)); + auto header = baggage->ToHeader(); + common::KeyValueStringTokenizer kv_str_tokenizer(header); + int expected_tokens = Baggage::kMaxKeyValuePairs; + EXPECT_EQ(kv_str_tokenizer.NumTokens(), expected_tokens); + + // For header with total size more than threshold, baggage is empty + int num_pairs_with_max_size = Baggage::kMaxSize / Baggage::kMaxKeyValueSize; + auto invalid_total_size_header = + header_with_custom_size(Baggage::kMaxKeyValueSize, num_pairs_with_max_size + 1); + EXPECT_EQ(Baggage::FromHeader(invalid_total_size_header.data())->ToHeader(), ""); +} + +TEST(BaggageTest, ValidateInjectHeader) +{ + struct + { + std::vector keys; + std::vector values; + const char *header; + } testcases[] = {{{"k1"}, {"v1"}, "k1=v1"}, + {{"k3", "k2", "k1"}, {"", "v2", "v1"}, "k1=v1,k2=v2,k3="}, // empty value + {{"1a-2f@foo", "a*/foo-_/bar"}, + {"bar%1", "bar 4"}, + "a%2A%2Ffoo-_%2Fbar=bar+4,1a-2f%40foo=bar%251"}, // encoding is done properly + {{"foo 1"}, + {"bar 1; metadata ; ;;"}, + "foo+1=bar+1; metadata ; ;;"}}; // metadata is added without encoding + + for (auto &testcase : testcases) + { + nostd::shared_ptr baggage(new Baggage{}); + for (size_t i = 0; i < testcase.keys.size(); i++) + { + baggage = baggage->Set(testcase.keys[i], testcase.values[i]); + } + EXPECT_EQ(baggage->ToHeader(), testcase.header); + } +} + +TEST(BaggageTest, BaggageGet) +{ + auto header = header_with_custom_entries(Baggage::kMaxKeyValuePairs); + auto baggage = Baggage::FromHeader(header); + + std::string value; + EXPECT_TRUE(baggage->GetValue("key0", value)); + EXPECT_EQ(value, "value0"); + EXPECT_TRUE(baggage->GetValue("key16", value)); + EXPECT_EQ(value, "value16"); + + EXPECT_TRUE(baggage->GetValue("key31", value)); + EXPECT_EQ(value, "value31"); + + EXPECT_FALSE(baggage->GetValue("key181", value)); +} + +TEST(BaggageTest, BaggageSet) +{ + std::string header = "k1=v1,k2=v2"; + auto baggage = Baggage::FromHeader(header); + + std::string value; + baggage = baggage->Set("k3", "v3"); + EXPECT_TRUE(baggage->GetValue("k3", value)); + EXPECT_EQ(value, "v3"); + + baggage = baggage->Set("k3", "v3_1"); // key should be updated with the latest value + EXPECT_TRUE(baggage->GetValue("k3", value)); + EXPECT_EQ(value, "v3_1"); + + header = header_with_custom_entries(Baggage::kMaxKeyValuePairs); + baggage = Baggage::FromHeader(header); + baggage = baggage->Set("key0", "0"); // updating on max list should work + EXPECT_TRUE(baggage->GetValue("key0", value)); + EXPECT_EQ(value, "0"); + + header = "k1=v1,k2=v2"; + baggage = Baggage::FromHeader(header); + baggage = baggage->Set("", "n_v1"); // adding invalid key, should return copy of same baggage + EXPECT_EQ(baggage->ToHeader(), header); + + header = "k1=v1,k2=v2"; + baggage = Baggage::FromHeader(header); + baggage = baggage->Set("k1", "\x1A"); // adding invalid value, should return copy of same baggage + EXPECT_EQ(baggage->ToHeader(), header); +} + +TEST(BaggageTest, BaggageRemove) +{ + auto header = header_with_custom_entries(Baggage::kMaxKeyValuePairs); + auto baggage = Baggage::FromHeader(header); + std::string value; + + // existing key is removed + EXPECT_TRUE(baggage->GetValue("key0", value)); + auto new_baggage = baggage->Delete("key0"); + EXPECT_FALSE(new_baggage->GetValue("key0", value)); + + // trying Delete on non existent key + EXPECT_FALSE(baggage->GetValue("key181", value)); + auto new_baggage_2 = baggage->Delete("key181"); + EXPECT_FALSE(new_baggage_2->GetValue("key181", value)); +} + +TEST(BaggageTest, BaggageGetAll) +{ + std::string baggage_header = "k1=v1,k2=v2,k3=v3"; + auto baggage = Baggage::FromHeader(baggage_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; + baggage->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; + }); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/BUILD new file mode 100644 index 000000000..1cd4371c1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/BUILD @@ -0,0 +1,16 @@ +load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") + +cc_test( + name = "baggage_propagator_test", + srcs = [ + "baggage_propagator_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/CMakeLists.txt new file mode 100644 index 000000000..3b7bd3d07 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/CMakeLists.txt @@ -0,0 +1,9 @@ +foreach(testname baggage_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 baggage. + TEST_LIST ${testname}) +endforeach() diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/baggage_propagator_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/baggage_propagator_test.cc new file mode 100644 index 000000000..94fe8b005 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/baggage/propagation/baggage_propagator_test.cc @@ -0,0 +1,113 @@ + +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/baggage/propagation/baggage_propagator.h" +#include +#include +#include +#include "opentelemetry/baggage/baggage_context.h" + +using namespace opentelemetry; +using namespace opentelemetry::baggage::propagation; + +class BaggageCarrierTest : public context::propagation::TextMapCarrier +{ +public: + BaggageCarrierTest() = default; + 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 headers_; +}; + +static BaggagePropagator format; + +TEST(BaggagePropagatorTest, ExtractNoBaggageHeader) +{ + BaggageCarrierTest carrier; + carrier.headers_ = {}; + context::Context ctx1 = context::Context{}; + context::Context ctx2 = format.Extract(carrier, ctx1); + auto ctx2_baggage = baggage::GetBaggage(ctx2); + EXPECT_EQ(ctx2_baggage->ToHeader(), ""); +} + +TEST(BaggagePropagatorTest, ExtractAndInjectBaggage) +{ + // create header string for baggage larger than allowed size (kMaxKeyValueSize) + std::string very_large_baggage_header = + std::string(baggage::Baggage::kMaxKeyValueSize / 2 + 1, 'k') + "=" + + std::string(baggage::Baggage::kMaxKeyValueSize / 2 + 1, 'v'); + + std::map baggages = { + {"key1=val1,key2=val2", "key1=val1,key2=val2"}, // valid header + {"key1 = val1, key2 =val2 ", "key1=val1,key2=val2"}, // valid header with spaces + {"key1=val1,key2=val2;prop=1", "key1=val1,key2=val2;prop=1"}, // valid header with properties + {"key%2C1=val1,key2=val2%2Cval3", + "key%2C1=val1,key2=val2%2Cval3"}, // valid header with url escape + {"key1=val1,key2=val2,a,val3", "key1=val1,key2=val2"}, // valid header with invalid value + {"key1=,key2=val2", "key1=,key2=val2"}, // valid header with empty value + {"invalid_header", ""}, // invalid header + {very_large_baggage_header, ""}}; // baggage header larger than allowed size. + + for (auto baggage : baggages) + { + BaggageCarrierTest carrier1; + carrier1.headers_[baggage::kBaggageHeader.data()] = baggage.first; + context::Context ctx1 = context::Context{}; + context::Context ctx2 = format.Extract(carrier1, ctx1); + + BaggageCarrierTest carrier2; + format.Inject(carrier2, ctx2); + EXPECT_EQ(carrier2.headers_[baggage::kBaggageHeader.data()], baggage.second); + + std::vector fields; + format.Fields([&fields](nostd::string_view field) { + fields.push_back(field.data()); + return true; + }); + EXPECT_EQ(fields.size(), 1); + EXPECT_EQ(fields[0], baggage::kBaggageHeader.data()); + } +} + +TEST(BaggagePropagatorTest, InjectEmptyHeader) +{ + // Test Missing baggage from context + BaggageCarrierTest carrier; + context::Context ctx = context::Context{}; + format.Inject(carrier, ctx); + EXPECT_EQ(carrier.headers_.find(baggage::kBaggageHeader), carrier.headers_.end()); + + { + // Test empty baggage in context + BaggageCarrierTest carrier1; + carrier1.headers_[baggage::kBaggageHeader.data()] = ""; + context::Context ctx1 = context::Context{}; + context::Context ctx2 = format.Extract(carrier1, ctx1); + format.Inject(carrier, ctx2); + EXPECT_EQ(carrier.headers_.find(baggage::kBaggageHeader), carrier.headers_.end()); + } + { + // Invalid baggage in context + BaggageCarrierTest carrier1; + carrier1.headers_[baggage::kBaggageHeader.data()] = "InvalidBaggageData"; + context::Context ctx1 = context::Context{}; + context::Context ctx2 = format.Extract(carrier1, ctx1); + + format.Inject(carrier, ctx2); + EXPECT_EQ(carrier.headers_.find(baggage::kBaggageHeader), carrier.headers_.end()); + } +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/common/BUILD new file mode 100644 index 000000000..5bfc1115d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/BUILD @@ -0,0 +1,41 @@ +load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") + +otel_cc_benchmark( + name = "spinlock_benchmark", + srcs = ["spinlock_benchmark.cc"], + tags = [ + "api", + "test", + ], + deps = ["//api"], +) + +cc_test( + name = "kv_properties_test", + srcs = [ + "kv_properties_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "string_util_test", + srcs = [ + "string_util_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/common/CMakeLists.txt new file mode 100644 index 000000000..5816b64b1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/CMakeLists.txt @@ -0,0 +1,15 @@ +include(GoogleTest) + +foreach(testname kv_properties_test string_util_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 common. + TEST_LIST ${testname}) +endforeach() + +add_executable(spinlock_benchmark spinlock_benchmark.cc) +target_link_libraries(spinlock_benchmark benchmark::benchmark + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/kv_properties_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/common/kv_properties_test.cc new file mode 100644 index 000000000..e5d9a2439 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/kv_properties_test.cc @@ -0,0 +1,235 @@ + +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include +#include +#include + +// ------------------------- Entry class tests --------------------------------- + +using namespace opentelemetry; +using opentelemetry::common::KeyValueProperties; +// Test constructor that takes a key-value pair +TEST(EntryTest, KeyValueConstruction) +{ + opentelemetry::nostd::string_view key = "test_key"; + opentelemetry::nostd::string_view val = "test_value"; + KeyValueProperties::Entry e(key, val); + + EXPECT_EQ(key.size(), e.GetKey().size()); + EXPECT_EQ(key, e.GetKey()); + + EXPECT_EQ(val.size(), e.GetValue().size()); + EXPECT_EQ(val, e.GetValue()); +} + +// Test copy constructor +TEST(EntryTest, Copy) +{ + KeyValueProperties::Entry e("test_key", "test_value"); + KeyValueProperties::Entry copy(e); + EXPECT_EQ(copy.GetKey(), e.GetKey()); + EXPECT_EQ(copy.GetValue(), e.GetValue()); +} + +// Test assignment operator +TEST(EntryTest, Assignment) +{ + KeyValueProperties::Entry e("test_key", "test_value"); + KeyValueProperties::Entry empty; + empty = e; + EXPECT_EQ(empty.GetKey(), e.GetKey()); + EXPECT_EQ(empty.GetValue(), e.GetValue()); +} + +TEST(EntryTest, SetValue) +{ + KeyValueProperties::Entry e("test_key", "test_value"); + opentelemetry::nostd::string_view new_val = "new_value"; + e.SetValue(new_val); + + EXPECT_EQ(new_val.size(), e.GetValue().size()); + EXPECT_EQ(new_val, e.GetValue()); +} + +// ------------------------- KeyValueStringTokenizer tests --------------------------------- + +using opentelemetry::common::KeyValueStringTokenizer; +using opentelemetry::common::KeyValueStringTokenizerOptions; + +TEST(KVStringTokenizer, SinglePair) +{ + bool valid_kv; + nostd::string_view key, value; + opentelemetry::nostd::string_view str = "k1=v1"; + KeyValueStringTokenizerOptions opts; + KeyValueStringTokenizer tk(str, opts); + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k1"); + EXPECT_EQ(value, "v1"); + EXPECT_FALSE(tk.next(valid_kv, key, value)); +} + +TEST(KVStringTokenizer, AcceptEmptyEntries) +{ + bool valid_kv; + nostd::string_view key, value; + opentelemetry::nostd::string_view str = ":k1=v1::k2=v2: "; + KeyValueStringTokenizerOptions opts; + opts.member_separator = ':'; + opts.ignore_empty_members = false; + + KeyValueStringTokenizer tk(str, opts); + EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k1"); + EXPECT_EQ(value, "v1"); + EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair + EXPECT_EQ(key, ""); + EXPECT_EQ(value, ""); + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair + EXPECT_FALSE(tk.next(valid_kv, key, value)); +} + +TEST(KVStringTokenizer, ValidPairsWithEmptyEntries) +{ + opentelemetry::nostd::string_view str = "k1:v1===k2:v2=="; + bool valid_kv; + nostd::string_view key, value; + KeyValueStringTokenizerOptions opts; + opts.member_separator = '='; + opts.key_value_separator = ':'; + + KeyValueStringTokenizer tk(str, opts); + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k1"); + EXPECT_EQ(value, "v1"); + + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k2"); + EXPECT_EQ(value, "v2"); + + EXPECT_FALSE(tk.next(valid_kv, key, value)); +} + +TEST(KVStringTokenizer, InvalidPairs) +{ + opentelemetry::nostd::string_view str = "k1=v1,invalid ,, k2=v2 ,invalid"; + KeyValueStringTokenizer tk(str); + bool valid_kv; + nostd::string_view key, value; + EXPECT_TRUE(tk.next(valid_kv, key, value)); + + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k1"); + EXPECT_EQ(value, "v1"); + + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_FALSE(valid_kv); + + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k2"); + EXPECT_EQ(value, "v2"); + + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_FALSE(valid_kv); + + EXPECT_FALSE(tk.next(valid_kv, key, value)); +} + +TEST(KVStringTokenizer, NumTokens) +{ + struct + { + const char *input; + size_t expected; + } testcases[] = {{"k1=v1", 1}, + {" ", 1}, + {"k1=v1,k2=v2,k3=v3", 3}, + {"k1=v1,", 1}, + {"k1=v1,k2=v2,invalidmember", 3}, + {"", 0}}; + for (auto &testcase : testcases) + { + KeyValueStringTokenizer tk(testcase.input); + EXPECT_EQ(tk.NumTokens(), testcase.expected); + } +} + +//------------------------- KeyValueProperties tests --------------------------------- + +TEST(KeyValueProperties, PopulateKVIterableContainer) +{ + std::vector> kv_pairs = {{"k1", "v1"}, {"k2", "v2"}}; + + auto kv_properties = KeyValueProperties(kv_pairs); + EXPECT_EQ(kv_properties.Size(), 2); + + std::string value; + bool present = kv_properties.GetValue("k1", value); + EXPECT_TRUE(present); + EXPECT_EQ(value, "v1"); + + present = kv_properties.GetValue("k2", value); + EXPECT_TRUE(present); + EXPECT_EQ(value, "v2"); +} + +TEST(KeyValueProperties, AddEntry) +{ + auto kv_properties = KeyValueProperties(1); + kv_properties.AddEntry("k1", "v1"); + std::string value; + bool present = kv_properties.GetValue("k1", value); + EXPECT_TRUE(present); + EXPECT_EQ(value, "v1"); + + kv_properties.AddEntry("k2", "v2"); // entry will not be added as max size reached. + EXPECT_EQ(kv_properties.Size(), 1); + present = kv_properties.GetValue("k2", value); + EXPECT_FALSE(present); +} + +TEST(KeyValueProperties, GetValue) +{ + auto kv_properties = KeyValueProperties(1); + kv_properties.AddEntry("k1", "v1"); + std::string value; + bool present = kv_properties.GetValue("k1", value); + EXPECT_TRUE(present); + EXPECT_EQ(value, "v1"); + + present = kv_properties.GetValue("k3", value); + EXPECT_FALSE(present); +} + +TEST(KeyValueProperties, GetAllEntries) +{ + std::vector> kv_pairs = { + {"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}}; + const size_t kNumPairs = 3; + opentelemetry::nostd::string_view keys[kNumPairs] = {"k1", "k2", "k3"}; + opentelemetry::nostd::string_view values[kNumPairs] = {"v1", "v2", "v3"}; + auto kv_properties = KeyValueProperties(kv_pairs); + + size_t index = 0; + kv_properties.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; + }); + + EXPECT_EQ(index, kNumPairs); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/spinlock_benchmark.cc b/src/jaegertracing/opentelemetry-cpp/api/test/common/spinlock_benchmark.cc new file mode 100644 index 000000000..07579579c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/spinlock_benchmark.cc @@ -0,0 +1,152 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/common/spin_lock_mutex.h" + +#include +#include + +namespace +{ +using opentelemetry::common::SpinLockMutex; + +constexpr int TightLoopLocks = 10000; + +// Runs a thrash-test where we spin up N threads, each of which will +// attempt to lock-mutate-unlock a total of `TightLoopLocks` times. +// +// lock: A lambda denoting how to lock. Accepts a reference to `SpinLockType`. +// unlock: A lambda denoting how to unlock. Accepts a reference to `SpinLockType`. +template +inline void SpinThrash(benchmark::State &s, SpinLockType &spinlock, LockF lock, UnlockF unlock) +{ + auto num_threads = s.range(0); + // Value we will increment, fighting over a spinlock. + // The contention is meant to be brief, as close to our expected + // use cases of "updating pointers" or "pushing an event onto a buffer". + std::int64_t value = 0; + + std::vector threads; + threads.reserve(num_threads); + + // Timing loop + for (auto _ : s) + { + for (auto i = 0; i < num_threads; i++) + { + threads.emplace_back([&] { + // Increment value once each time the lock is acquired. Spin a few times + // to ensure maximum thread contention. + for (int i = 0; i < TightLoopLocks; i++) + { + lock(spinlock); + value++; + unlock(spinlock); + } + }); + } + // Join threads + for (auto &thread : threads) + thread.join(); + threads.clear(); + } +} + +// Benchmark of full spin-lock implementation. +static void BM_SpinLockThrashing(benchmark::State &s) +{ + SpinLockMutex spinlock; + SpinThrash( + s, spinlock, [](SpinLockMutex &m) { m.lock(); }, [](SpinLockMutex &m) { m.unlock(); }); +} + +// Naive `while(try_lock()) {}` implementation of lock. +static void BM_NaiveSpinLockThrashing(benchmark::State &s) +{ + SpinLockMutex spinlock; + SpinThrash( + s, spinlock, + [](SpinLockMutex &m) { + while (!m.try_lock()) + { + // Left this comment to keep the same format on old and new versions of clang-format + } + }, + [](SpinLockMutex &m) { m.unlock(); }); +} + +// Simple `while(try_lock()) { yield-processor }` +static void BM_ProcYieldSpinLockThrashing(benchmark::State &s) +{ + SpinLockMutex spinlock; + SpinThrash( + s, spinlock, + [](SpinLockMutex &m) { + while (!m.try_lock()) + { +#if defined(_MSC_VER) + YieldProcessor(); +#elif defined(__i386__) || defined(__x86_64__) +# if defined(__clang__) + _mm_pause(); +# else + __builtin_ia32_pause(); +# endif +#elif defined(__arm__) + __asm__ volatile("yield" ::: "memory"); +#endif + } + }, + [](SpinLockMutex &m) { m.unlock(); }); +} + +// SpinLock thrashing with thread::yield(). +static void BM_ThreadYieldSpinLockThrashing(benchmark::State &s) +{ + std::atomic_flag mutex = ATOMIC_FLAG_INIT; + SpinThrash( + s, mutex, + [](std::atomic_flag &l) { + uint32_t try_count = 0; + while (l.test_and_set(std::memory_order_acq_rel)) + { + ++try_count; + if (try_count % 32) + { + std::this_thread::yield(); + } + } + std::this_thread::yield(); + }, + [](std::atomic_flag &l) { l.clear(std::memory_order_release); }); +} + +// Run the benchmarks at 2x thread/core and measure the amount of time to thrash around. +BENCHMARK(BM_SpinLockThrashing) + ->RangeMultiplier(2) + ->Range(1, std::thread::hardware_concurrency()) + ->MeasureProcessCPUTime() + ->UseRealTime() + ->Unit(benchmark::kMillisecond); +BENCHMARK(BM_ProcYieldSpinLockThrashing) + ->RangeMultiplier(2) + ->Range(1, std::thread::hardware_concurrency()) + ->MeasureProcessCPUTime() + ->UseRealTime() + ->Unit(benchmark::kMillisecond); +BENCHMARK(BM_NaiveSpinLockThrashing) + ->RangeMultiplier(2) + ->Range(1, std::thread::hardware_concurrency()) + ->MeasureProcessCPUTime() + ->UseRealTime() + ->Unit(benchmark::kMillisecond); +BENCHMARK(BM_ThreadYieldSpinLockThrashing) + ->RangeMultiplier(2) + ->Range(1, std::thread::hardware_concurrency()) + ->MeasureProcessCPUTime() + ->UseRealTime() + ->Unit(benchmark::kMillisecond); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/common/string_util_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/common/string_util_test.cc new file mode 100644 index 000000000..da2e63511 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/common/string_util_test.cc @@ -0,0 +1,47 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include +#include +#include + +// ------------------------- StringUtil class tests --------------------------------- + +using opentelemetry::common::StringUtil; + +TEST(StringUtilTest, TrimStringWithIndex) +{ + struct + { + const char *input; + const char *expected; + } testcases[] = {{"k1=v1", "k1=v1"}, {"k1=v1,k2=v2, k3=v3", "k1=v1,k2=v2, k3=v3"}, + {" k1=v1", "k1=v1"}, {"k1=v1 ", "k1=v1"}, + {" k1=v1 ", "k1=v1"}, {" ", ""}}; + for (auto &testcase : testcases) + { + EXPECT_EQ(StringUtil::Trim(testcase.input, 0, strlen(testcase.input) - 1), testcase.expected); + } +} + +TEST(StringUtilTest, TrimString) +{ + struct + { + const char *input; + const char *expected; + } testcases[] = {{"k1=v1", "k1=v1"}, + {"k1=v1,k2=v2, k3=v3", "k1=v1,k2=v2, k3=v3"}, + {" k1=v1", "k1=v1"}, + {"k1=v1 ", "k1=v1"}, + {" k1=v1 ", "k1=v1"}, + {" ", ""}, + {"", ""}}; + for (auto &testcase : testcases) + { + EXPECT_EQ(StringUtil::Trim(testcase.input), testcase.expected); + } +} 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 + +#include + +using namespace opentelemetry; + +// Tests that the context constructor accepts an std::map. +TEST(ContextTest, ContextIterableAcceptsMap) +{ + std::map 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 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(test_context.GetValue("test_key")), 123); + EXPECT_EQ(nostd::get(test_context.GetValue("foo_key")), 456); +} + +// Tests that the SetValues method accepts an std::map. +TEST(ContextTest, ContextSetValuesAcceptsMap) +{ + std::map map_test = {{"test_key", (int64_t)123}}; + std::map 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(foo_context.GetValue("test_key")), 123); + EXPECT_EQ(nostd::get(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(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 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(context_test.GetValue("foo_key"))); +} + +// Tests that writing the same to a context overwrites the original value. +TEST(ContextTest, ContextKeyOverwrite) +{ + std::map 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(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; + + 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(foo_context.GetValue("test_key")), 123); + EXPECT_EQ(nostd::get(foo_context.GetValue("foo_key")), 321); + EXPECT_EQ(nostd::get(foo_context.GetValue("other_key")), 789); + EXPECT_EQ(nostd::get(foo_context.GetValue("another_key")), 987); + + EXPECT_TRUE(nostd::holds_alternative(test_context.GetValue("other_key"))); + EXPECT_TRUE(nostd::holds_alternative(test_context.GetValue("another_key"))); +} + +// Tests that copying a context copies the key value pairs as expected. +TEST(ContextTest, ContextCopyOperator) +{ + std::map 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(copied_context.GetValue("test_key")), 123); + EXPECT_EQ(nostd::get(copied_context.GetValue("foo_key")), 456); + EXPECT_EQ(nostd::get(copied_context.GetValue("other_key")), 789); +} + +// Tests that the Context accepts an empty map. +TEST(ContextTest, ContextEmptyMap) +{ + std::map 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 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 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 map_test = {{"test_key", (int64_t)123}}; + std::map 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 +#include +#include + +#include + +using namespace opentelemetry; + +template +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 headers_; +}; + +class CompositePropagatorTest : public ::testing::Test +{ + +public: + CompositePropagatorTest() + { + std::vector> propogator_list = {}; + std::unique_ptr w3c_propogator( + new trace::propagation::HttpTraceContext()); + std::unique_ptr 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>(ctx2_span)); + + auto span = nostd::get>(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 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 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 + +using namespace opentelemetry; + +// Tests that GetCurrent returns the current context +TEST(RuntimeContextTest, GetCurrent) +{ + std::map 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 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 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 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(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", (int64_t)596); + context::Context test_context = + context::RuntimeContext::SetValue("test_key", (int64_t)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", (int64_t)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", (int64_t)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; + for (auto i : indices) + { + contexts.push_back(context::Context("index", (int64_t)i)); + } + + do + { + std::vector> 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())); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/core/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/core/BUILD new file mode 100644 index 000000000..99fcfaeca --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/core/BUILD @@ -0,0 +1,14 @@ +cc_test( + name = "timestamp_test", + srcs = [ + "timestamp_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/core/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/core/CMakeLists.txt new file mode 100644 index 000000000..7fead491e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/core/CMakeLists.txt @@ -0,0 +1,9 @@ +include(GoogleTest) + +add_executable(timestamp_test timestamp_test.cc) +target_link_libraries(timestamp_test ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) +gtest_add_tests( + TARGET timestamp_test + TEST_PREFIX trace. + TEST_LIST timestamp_test) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/core/timestamp_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/core/timestamp_test.cc new file mode 100644 index 000000000..8efc0215b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/core/timestamp_test.cc @@ -0,0 +1,67 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/common/timestamp.h" + +#include + +using opentelemetry::common::SteadyTimestamp; +using opentelemetry::common::SystemTimestamp; + +template +static bool AreNearlyEqual(const Timestamp &t1, const Timestamp &t2) noexcept +{ + return std::abs(std::chrono::duration_cast(t2 - t1).count()) < 2; +} + +TEST(SystemTimestampTest, Construction) +{ + auto now_system = std::chrono::system_clock::now(); + + SystemTimestamp t1; + EXPECT_EQ(t1.time_since_epoch(), std::chrono::nanoseconds{0}); + + SystemTimestamp t2{now_system}; + EXPECT_TRUE(AreNearlyEqual(now_system, static_cast(t2))); + EXPECT_EQ(std::chrono::duration_cast(now_system.time_since_epoch()), + t2.time_since_epoch()); +} + +TEST(SystemTimestampTest, Comparison) +{ + SystemTimestamp t1; + SystemTimestamp t2; + SystemTimestamp t3{std::chrono::nanoseconds{2}}; + + EXPECT_EQ(t1, t1); + EXPECT_EQ(t1, t2); + EXPECT_EQ(t2, t1); + EXPECT_NE(t1, t3); + EXPECT_NE(t3, t1); +} + +TEST(SteadyTimestampTest, Construction) +{ + auto now_steady = std::chrono::steady_clock::now(); + + SteadyTimestamp t1; + EXPECT_EQ(t1.time_since_epoch(), std::chrono::nanoseconds{0}); + + SteadyTimestamp t2{now_steady}; + EXPECT_TRUE(AreNearlyEqual(now_steady, static_cast(t2))); + EXPECT_EQ(std::chrono::duration_cast(now_steady.time_since_epoch()), + t2.time_since_epoch()); +} + +TEST(SteadyTimestampTest, Comparison) +{ + SteadyTimestamp t1; + SteadyTimestamp t2; + SteadyTimestamp t3{std::chrono::nanoseconds{2}}; + + EXPECT_EQ(t1, t1); + EXPECT_EQ(t1, t2); + EXPECT_EQ(t2, t1); + EXPECT_NE(t1, t3); + EXPECT_NE(t3, t1); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/logs/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/logs/BUILD new file mode 100644 index 000000000..34fda18db --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/logs/BUILD @@ -0,0 +1,33 @@ +load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") + +cc_test( + name = "provider_test", + srcs = [ + "provider_test.cc", + ], + tags = [ + "api", + "logs", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "logger_test", + srcs = [ + "logger_test.cc", + ], + tags = [ + "api", + "logs", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/logs/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/logs/CMakeLists.txt new file mode 100644 index 000000000..a5f9c0408 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/logs/CMakeLists.txt @@ -0,0 +1,9 @@ +foreach(testname provider_test logger_test) + add_executable(logs_api_${testname} "${testname}.cc") + target_link_libraries(logs_api_${testname} ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) + gtest_add_tests( + TARGET logs_api_${testname} + TEST_PREFIX logs. + TEST_LIST logs_api_${testname}) +endforeach() diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/logs/logger_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/logs/logger_test.cc new file mode 100644 index 000000000..07480ef44 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/logs/logger_test.cc @@ -0,0 +1,165 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include +# include + +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/logs/provider.h" +# include "opentelemetry/nostd/shared_ptr.h" + +using opentelemetry::logs::Logger; +using opentelemetry::logs::LoggerProvider; +using opentelemetry::logs::Provider; +using opentelemetry::logs::Severity; +using opentelemetry::nostd::shared_ptr; +using opentelemetry::nostd::span; +using opentelemetry::nostd::string_view; +namespace common = opentelemetry::common; +namespace nostd = opentelemetry::nostd; +namespace trace = opentelemetry::trace; + +// Check that the default logger is a noop logger instance +TEST(Logger, GetLoggerDefault) +{ + auto lp = Provider::GetLoggerProvider(); + const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; + auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); + auto name = logger->GetName(); + EXPECT_NE(nullptr, logger); + EXPECT_EQ(name, "noop logger"); +} + +// Test the two additional overloads for GetLogger() +TEST(Logger, GetNoopLoggerNameWithArgs) +{ + auto lp = Provider::GetLoggerProvider(); + + // GetLogger(name, list(args)) + std::array sv{"string"}; + span args{sv}; + const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; + lp->GetLogger("NoopLoggerWithArgs", args, "opentelelemtry_library", "", schema_url); + + // GetLogger(name, string options) + lp->GetLogger("NoopLoggerWithOptions", "options", "opentelelemtry_library", "", schema_url); +} + +// Test the Log() overloads +TEST(Logger, LogMethodOverloads) +{ + auto lp = Provider::GetLoggerProvider(); + const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; + auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); + + // Create a map to test the logs with + std::map m = {{"key1", "value1"}}; + + // Log overloads + logger->Log(Severity::kTrace, "Test log message"); + logger->Log(Severity::kInfo, "Test log message"); + logger->Log(Severity::kDebug, m); + logger->Log(Severity::kWarn, "Logging a map", m); + logger->Log(Severity::kError, {{"key1", "value 1"}, {"key2", 2}}); + logger->Log(Severity::kFatal, "Logging an initializer list", {{"key1", "value 1"}, {"key2", 2}}); + + // Deprecated Log overloads + logger->Log(Severity::kTrace, "Log name", "Test log message"); + logger->Log(Severity::kWarn, "Log name", "Logging a map", m, {}, {}, {}, + std::chrono::system_clock::now()); + logger->Log(Severity::kError, "Log name", "Logging a map", {{"key1", "value 1"}, {"key2", 2}}, {}, + {}, {}, std::chrono::system_clock::now()); + logger->Trace("Log name", "Test log message"); + logger->Debug("Log name", "Test log message"); + logger->Info("Log name", "Test log message"); + logger->Warn("Log name", "Test log message"); + logger->Error("Log name", "Test log message"); + logger->Fatal("Log name", "Test log message"); + + // Severity methods + logger->Trace("Test log message"); + logger->Trace("Test log message", m); + logger->Trace("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Trace(m); + logger->Trace({{"key1", "value 1"}, {"key2", 2}}); + logger->Debug("Test log message"); + logger->Debug("Test log message", m); + logger->Debug("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Debug(m); + logger->Debug({{"key1", "value 1"}, {"key2", 2}}); + logger->Info("Test log message"); + logger->Info("Test log message", m); + logger->Info("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Info(m); + logger->Info({{"key1", "value 1"}, {"key2", 2}}); + logger->Warn("Test log message"); + logger->Warn("Test log message", m); + logger->Warn("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Warn(m); + logger->Warn({{"key1", "value 1"}, {"key2", 2}}); + logger->Error("Test log message"); + logger->Error("Test log message", m); + logger->Error("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Error(m); + logger->Error({{"key1", "value 1"}, {"key2", 2}}); + logger->Fatal("Test log message"); + logger->Fatal("Test log message", m); + logger->Fatal("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Fatal(m); + logger->Fatal({{"key1", "value 1"}, {"key2", 2}}); +} + +// Define a basic Logger class +class TestLogger : public Logger +{ + const nostd::string_view GetName() noexcept override { return "test logger"; } + + void Log(Severity severity, + string_view body, + const common::KeyValueIterable &attributes, + trace::TraceId trace_id, + trace::SpanId span_id, + trace::TraceFlags trace_flags, + common::SystemTimestamp timestamp) noexcept override + {} +}; + +// Define a basic LoggerProvider class that returns an instance of the logger class defined above +class TestProvider : public LoggerProvider +{ + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override + { + return shared_ptr(new TestLogger()); + } + + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::span args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override + { + return shared_ptr(new TestLogger()); + } +}; + +TEST(Logger, PushLoggerImplementation) +{ + // Push the new loggerprovider class into the global singleton + auto test_provider = shared_ptr(new TestProvider()); + Provider::SetLoggerProvider(test_provider); + + auto lp = Provider::GetLoggerProvider(); + + // Check that the implementation was pushed by calling TestLogger's GetName() + nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"}; + auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); + ASSERT_EQ("test logger", logger->GetName()); +} +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/logs/provider_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/logs/provider_test.cc new file mode 100644 index 000000000..64a6b0a86 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/logs/provider_test.cc @@ -0,0 +1,77 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include +# include + +# include "opentelemetry/logs/provider.h" +# include "opentelemetry/nostd/shared_ptr.h" + +using opentelemetry::logs::Logger; +using opentelemetry::logs::LoggerProvider; +using opentelemetry::logs::Provider; +using opentelemetry::nostd::shared_ptr; +namespace nostd = opentelemetry::nostd; + +class TestProvider : public LoggerProvider +{ + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override + { + return shared_ptr(nullptr); + } + + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::span args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override + { + return shared_ptr(nullptr); + } +}; + +TEST(Provider, GetLoggerProviderDefault) +{ + auto tf = Provider::GetLoggerProvider(); + EXPECT_NE(nullptr, tf); +} + +TEST(Provider, SetLoggerProvider) +{ + auto tf = shared_ptr(new TestProvider()); + Provider::SetLoggerProvider(tf); + ASSERT_EQ(tf, Provider::GetLoggerProvider()); +} + +TEST(Provider, MultipleLoggerProviders) +{ + auto tf = shared_ptr(new TestProvider()); + Provider::SetLoggerProvider(tf); + auto tf2 = shared_ptr(new TestProvider()); + Provider::SetLoggerProvider(tf2); + + ASSERT_NE(Provider::GetLoggerProvider(), tf); +} + +TEST(Provider, GetLogger) +{ + auto tf = shared_ptr(new TestProvider()); + // tests GetLogger(name, version, schema) + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = tf->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); + EXPECT_EQ(nullptr, logger); + + // tests GetLogger(name, arguments) + + std::array sv{"string"}; + nostd::span args{sv}; + auto logger2 = tf->GetLogger("logger2", args, "opentelelemtry_library", "", schema_url); + EXPECT_EQ(nullptr, logger2); +} +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/metrics/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/BUILD new file mode 100644 index 000000000..d15d7511f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/BUILD @@ -0,0 +1,31 @@ +load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") + +cc_test( + name = "noop_sync_instrument_test", + srcs = [ + "noop_sync_instrument_test.cc", + ], + tags = [ + "metrics", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "meter_provider_test", + srcs = [ + "meter_provider_test.cc", + ], + tags = [ + "metrics", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/metrics/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/CMakeLists.txt new file mode 100644 index 000000000..89ce81fd0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/CMakeLists.txt @@ -0,0 +1,9 @@ +foreach(testname meter_provider_test noop_sync_instrument_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 metrics_new. + TEST_LIST ${testname}) +endforeach() diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/metrics/meter_provider_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/meter_provider_test.cc new file mode 100644 index 000000000..161d852f0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/meter_provider_test.cc @@ -0,0 +1,38 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifndef ENABLE_METRICS_PREVIEW + +# include +# include "opentelemetry/metrics/noop.h" +# include "opentelemetry/metrics/provider.h" +# include "opentelemetry/nostd/shared_ptr.h" + +using opentelemetry::metrics::Meter; +using opentelemetry::metrics::MeterProvider; +using opentelemetry::metrics::NoopMeterProvider; +using opentelemetry::metrics::Provider; + +TEST(Provider, GetMeterProviderDefault) +{ + auto tf = Provider::GetMeterProvider(); + EXPECT_NE(nullptr, tf); +} + +TEST(Provider, SetMeterProvider) +{ + auto tf = opentelemetry::nostd::shared_ptr(new NoopMeterProvider()); + Provider::SetMeterProvider(tf); + ASSERT_EQ(tf, Provider::GetMeterProvider()); +} + +TEST(Provider, MultipleMeterProviders) +{ + auto tf = opentelemetry::nostd::shared_ptr(new NoopMeterProvider()); + Provider::SetMeterProvider(tf); + auto tf2 = opentelemetry::nostd::shared_ptr(new NoopMeterProvider()); + Provider::SetMeterProvider(tf2); + + ASSERT_NE(Provider::GetMeterProvider(), tf); +} +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/metrics/noop_sync_instrument_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/noop_sync_instrument_test.cc new file mode 100644 index 000000000..62be4f34a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/metrics/noop_sync_instrument_test.cc @@ -0,0 +1,50 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifndef ENABLE_METRICS_PREVIEW + +# include +# include +# include "opentelemetry/metrics/noop.h" + +TEST(Counter, Add) +{ + std::shared_ptr> counter{ + new opentelemetry::metrics::NoopCounter("test", "none", "unitless")}; + + std::map labels = {{"k1", "v1"}}; + EXPECT_NO_THROW(counter->Add(10l, labels)); + EXPECT_NO_THROW(counter->Add(10l, labels, opentelemetry::context::Context{})); + EXPECT_NO_THROW(counter->Add(2l)); + EXPECT_NO_THROW(counter->Add(2l, opentelemetry::context::Context{})); + EXPECT_NO_THROW(counter->Add(10l, {{"k1", "1"}, {"k2", 2}})); + EXPECT_NO_THROW(counter->Add(10l, {{"k1", "1"}, {"k2", 2}}, opentelemetry::context::Context{})); +} + +TEST(histogram, Record) +{ + std::shared_ptr> counter{ + new opentelemetry::metrics::NoopHistogram("test", "none", "unitless")}; + + std::map labels = {{"k1", "v1"}}; + EXPECT_NO_THROW(counter->Record(10l, labels, opentelemetry::context::Context{})); + EXPECT_NO_THROW(counter->Record(2l, opentelemetry::context::Context{})); + EXPECT_NO_THROW( + counter->Record(10l, {{"k1", "1"}, {"k2", 2}}, opentelemetry::context::Context{})); +} + +TEST(UpDownCountr, Record) +{ + std::shared_ptr> counter{ + new opentelemetry::metrics::NoopUpDownCounter("test", "none", "unitless")}; + + std::map labels = {{"k1", "v1"}}; + EXPECT_NO_THROW(counter->Add(10l, labels)); + EXPECT_NO_THROW(counter->Add(10l, labels, opentelemetry::context::Context{})); + EXPECT_NO_THROW(counter->Add(2l)); + EXPECT_NO_THROW(counter->Add(2l, opentelemetry::context::Context{})); + EXPECT_NO_THROW(counter->Add(10l, {{"k1", "1"}, {"k2", 2}})); + EXPECT_NO_THROW(counter->Add(10l, {{"k1", "1"}, {"k2", 2}}, opentelemetry::context::Context{})); +} + +#endif \ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/BUILD new file mode 100644 index 000000000..75166c5de --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/BUILD @@ -0,0 +1,104 @@ +cc_test( + name = "function_ref_test", + srcs = [ + "function_ref_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "string_view_test", + srcs = [ + "string_view_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "variant_test", + srcs = [ + "variant_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "unique_ptr_test", + srcs = [ + "unique_ptr_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "utility_test", + srcs = [ + "utility_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "span_test", + srcs = [ + "span_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "shared_ptr_test", + srcs = [ + "shared_ptr_test.cc", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/CMakeLists.txt new file mode 100644 index 000000000..dd783bf2d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/CMakeLists.txt @@ -0,0 +1,19 @@ +include(GoogleTest) + +foreach( + testname + function_ref_test + string_view_test + unique_ptr_test + utility_test + span_test + shared_ptr_test + variant_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 nostd. + TEST_LIST ${testname}) +endforeach() diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/function_ref_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/function_ref_test.cc new file mode 100644 index 000000000..1153360d2 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/function_ref_test.cc @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/function_ref.h" + +#include +using namespace opentelemetry::nostd; + +int Call(function_ref f) +{ + return f(); +} + +int Return3() +{ + return 3; +} + +TEST(FunctionRefTest, Call) +{ + int x = 9; + + auto f = [&] { return x; }; + EXPECT_EQ(Call(f), 9); + + EXPECT_EQ(Call(Return3), 3); +} + +TEST(FunctionRefTest, BoolConversion) +{ + auto f = [] { return 0; }; + function_ref fref1{nullptr}; + function_ref fref2{f}; + EXPECT_TRUE(!static_cast(fref1)); + EXPECT_TRUE(static_cast(fref2)); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/shared_ptr_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/shared_ptr_test.cc new file mode 100644 index 000000000..6f3d43a77 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/shared_ptr_test.cc @@ -0,0 +1,189 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/shared_ptr.h" + +#include + +#include + +using opentelemetry::nostd::shared_ptr; + +class A +{ +public: + explicit A(bool &destructed) noexcept : destructed_{destructed} { destructed_ = false; } + + ~A() { destructed_ = true; } + +private: + bool &destructed_; +}; + +class B +{ +public: + int f() const { return 123; } +}; + +class C +{ +public: + virtual ~C() {} +}; + +class D : public C +{ +public: + virtual ~D() {} +}; + +TEST(SharedPtrTest, DefaultConstruction) +{ + shared_ptr ptr1; + EXPECT_EQ(ptr1.get(), nullptr); + + shared_ptr ptr2{nullptr}; + EXPECT_EQ(ptr2.get(), nullptr); +} + +TEST(SharedPtrTest, ExplicitConstruction) +{ + auto c = new C(); + shared_ptr ptr1{c}; + EXPECT_EQ(ptr1.get(), c); + + auto d = new D(); + shared_ptr ptr2{d}; + EXPECT_EQ(ptr2.get(), d); +} + +TEST(SharedPtrTest, MoveConstruction) +{ + auto value = new int{123}; + shared_ptr ptr1{value}; + shared_ptr ptr2{std::move(ptr1)}; + EXPECT_EQ(ptr1.get(), nullptr); + EXPECT_EQ(ptr2.get(), value); +} + +TEST(SharedPtrTest, MoveConstructionFromDifferentType) +{ + auto value = new int{123}; + shared_ptr ptr1{value}; + shared_ptr ptr2{std::move(ptr1)}; + EXPECT_EQ(ptr1.get(), nullptr); + EXPECT_EQ(ptr2.get(), value); +} + +TEST(SharedPtrTest, MoveConstructionFromStdSharedPtr) +{ + auto value = new int{123}; + std::shared_ptr ptr1{value}; + shared_ptr ptr2{std::move(ptr1)}; + EXPECT_EQ(ptr1.get(), nullptr); + EXPECT_EQ(ptr2.get(), value); +} + +TEST(SharedPtrTest, Destruction) +{ + bool was_destructed; + shared_ptr{new A{was_destructed}}; + EXPECT_TRUE(was_destructed); +} + +TEST(SharedPtrTest, Assignment) +{ + auto value = new int{123}; + shared_ptr ptr1; + + ptr1 = shared_ptr(value); + EXPECT_EQ(ptr1.get(), value); + + ptr1 = nullptr; + EXPECT_EQ(ptr1.get(), nullptr); + + auto value2 = new int{234}; + const shared_ptr ptr2 = shared_ptr(value2); + ptr1 = ptr2; + EXPECT_EQ(ptr1.get(), value2); + + auto value3 = new int{345}; + std::shared_ptr ptr3(value3); + ptr1 = ptr3; + EXPECT_EQ(ptr1.get(), value3); +} + +TEST(SharedPtrTest, BoolConversionOpertor) +{ + auto value = new int{123}; + shared_ptr ptr1{value}; + + EXPECT_TRUE(ptr1); + EXPECT_FALSE(shared_ptr{}); +} + +TEST(SharedPtrTest, PointerOperators) +{ + auto value = new int{123}; + shared_ptr ptr1{value}; + + EXPECT_EQ(&*ptr1, value); + EXPECT_EQ( + shared_ptr { new B }->f(), 123); +} + +TEST(SharedPtrTest, Swap) +{ + auto value1 = new int{123}; + shared_ptr ptr1{value1}; + + auto value2 = new int{456}; + shared_ptr ptr2{value2}; + ptr1.swap(ptr2); + + EXPECT_EQ(ptr1.get(), value2); + EXPECT_EQ(ptr2.get(), value1); +} + +TEST(SharedPtrTest, Comparison) +{ + shared_ptr ptr1{new int{123}}; + shared_ptr ptr2{new int{456}}; + shared_ptr ptr3{}; + + EXPECT_EQ(ptr1, ptr1); + EXPECT_NE(ptr1, ptr2); + + EXPECT_NE(ptr1, nullptr); + EXPECT_NE(nullptr, ptr1); + + EXPECT_EQ(ptr3, nullptr); + EXPECT_EQ(nullptr, ptr3); +} + +static void SharedPtrTest_Sort(size_t size = 10) +{ + std::vector> nums; + + for (int i = static_cast(size); i > 0; i--) + { + nums.push_back(shared_ptr(new int(i))); + } + + auto nums2 = nums; + + std::sort(nums.begin(), nums.end(), + [](shared_ptr a, shared_ptr b) { return *a < *b; }); + + EXPECT_NE(nums, nums2); + + std::reverse(nums2.begin(), nums2.end()); + + EXPECT_EQ(nums, nums2); +} + +TEST(SharedPtrTest, Sort) +{ + SharedPtrTest_Sort(); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/span_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/span_test.cc new file mode 100644 index 000000000..09d32ecfb --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/span_test.cc @@ -0,0 +1,191 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/span.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include + +using opentelemetry::nostd::span; + +TEST(SpanTest, DefaultConstruction) +{ + span s1; + EXPECT_EQ(s1.data(), nullptr); + EXPECT_EQ(s1.size(), 0); + EXPECT_TRUE(s1.empty()); + + span s2; + EXPECT_EQ(s2.data(), nullptr); + EXPECT_EQ(s2.size(), 0); + EXPECT_TRUE(s2.empty()); + + EXPECT_FALSE((std::is_default_constructible>::value)); +} + +TEST(SpanTest, Assignment) +{ + std::array array1 = {1, 2, 3}; + std::array array2 = {1, 2, 3}; + span s1{array1.data(), array1.size()}; + span s2{array1.data(), array1.size()}; + + span s3; + s3 = s1; + EXPECT_EQ(s3.data(), array1.data()); + EXPECT_EQ(s3.size(), array1.size()); + + span s4{array2}; + s4 = s2; + EXPECT_EQ(s4.data(), array1.data()); + EXPECT_EQ(s4.size(), array1.size()); +} + +TEST(SpanTest, PointerCountConstruction) +{ + std::array array = {1, 2, 3}; + + span s1{array.data(), array.size()}; + EXPECT_EQ(s1.data(), array.data()); + EXPECT_EQ(s1.size(), array.size()); + + span s2{array.data(), array.size()}; + EXPECT_EQ(s2.data(), array.data()); + EXPECT_EQ(s2.size(), array.size()); + +#ifndef HAVE_CPP_STDLIB + /* This test is not supposed to fail with STL. Why is this invalid construct? */ + EXPECT_DEATH((span{array.data(), array.size()}), ".*"); +#endif +} + +TEST(SpanTest, RangeConstruction) +{ + int array[] = {1, 2, 3}; + + span s1{std::begin(array), std::end(array)}; + EXPECT_EQ(s1.data(), array); + EXPECT_EQ(s1.size(), 3); + + span s2{std::begin(array), std::end(array)}; + EXPECT_EQ(s2.data(), array); + EXPECT_EQ(s2.size(), 3); + +#ifndef HAVE_CPP_STDLIB + /* This test is not supposed to fail with STL. Why is this invalid construct? */ + EXPECT_DEATH((span{std::begin(array), std::end(array)}), ".*"); +#endif +} + +TEST(SpanTest, ArrayConstruction) +{ + int array1[] = {1, 2, 3}; + std::array array2 = {1, 2, 3}; + + span s1{array1}; + EXPECT_EQ(s1.data(), array1); + EXPECT_EQ(s1.size(), 3); + + span s2{array2}; + EXPECT_EQ(s2.data(), array2.data()); + EXPECT_EQ(s2.size(), array2.size()); + + span s3{array1}; + EXPECT_EQ(s3.data(), array1); + EXPECT_EQ(s3.size(), 3); + + span s4{array2}; + EXPECT_EQ(s4.data(), array2.data()); + EXPECT_EQ(s4.size(), array2.size()); + + EXPECT_FALSE((std::is_constructible, int(&)[3]>::value)); +} + +TEST(SpanTest, ContainerConstruction) +{ + std::vector v = {1, 2, 3}; + + span s1{v}; + EXPECT_EQ(s1.data(), v.data()); + EXPECT_EQ(s1.size(), v.size()); + + span s2{v.data(), 3}; + + EXPECT_EQ(s2.data(), v.data()); + EXPECT_EQ(s2.size(), v.size()); + +#ifndef HAVE_CPP_STDLIB + /* This test is not supposed to fail with STL. Why is this invalid construct? */ + EXPECT_DEATH((span{v.data(), 3}), ".*"); +#endif + + EXPECT_FALSE((std::is_constructible, std::vector>::value)); + EXPECT_FALSE((std::is_constructible, std::list>::value)); +} + +TEST(SpanTest, OtherSpanConstruction) +{ + std::array array = {1, 2, 3}; + span s1{array.data(), array.size()}; + span s2{array.data(), array.size()}; + + span s3{s1}; + EXPECT_EQ(s3.data(), array.data()); + EXPECT_EQ(s3.size(), array.size()); + + span s4{s2}; + EXPECT_EQ(s4.data(), array.data()); + EXPECT_EQ(s4.size(), array.size()); + + span s5{s1}; + EXPECT_EQ(s5.data(), array.data()); + EXPECT_EQ(s5.size(), array.size()); + + EXPECT_FALSE((std::is_constructible, span>::value)); + EXPECT_FALSE((std::is_constructible, span>::value)); + + span s6{s2}; + EXPECT_EQ(s6.data(), array.data()); + EXPECT_EQ(s6.size(), array.size()); + + span s7{s2}; + EXPECT_EQ(s7.data(), array.data()); + EXPECT_EQ(s7.size(), array.size()); + + EXPECT_FALSE((std::is_constructible, span>::value)); + EXPECT_FALSE((std::is_constructible, span>::value)); +} + +TEST(SpanTest, BracketOperator) +{ + std::array array = {1, 2}; + + span s1{array.data(), array.size()}; + EXPECT_EQ(s1[0], 1); + EXPECT_EQ(s1[1], 2); + + span s2{array.data(), array.size()}; + EXPECT_EQ(s2[0], 1); + EXPECT_EQ(s2[1], 2); +} + +TEST(SpanTest, Iteration) +{ + std::array array = {1, 2, 3}; + + span s1{array.data(), array.size()}; + EXPECT_EQ(std::distance(s1.begin(), s1.end()), array.size()); + EXPECT_TRUE(std::equal(s1.begin(), s1.end(), array.begin())); + + span s2{array.data(), array.size()}; + EXPECT_EQ(std::distance(s2.begin(), s2.end()), array.size()); + EXPECT_TRUE(std::equal(s2.begin(), s2.end(), array.begin())); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/string_view_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/string_view_test.cc new file mode 100644 index 000000000..fc580debc --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/string_view_test.cc @@ -0,0 +1,125 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/string_view.h" + +#include +#include +#include + +using opentelemetry::nostd::string_view; + +TEST(StringViewTest, DefaultConstruction) +{ + string_view ref; + EXPECT_EQ(ref.data(), nullptr); + EXPECT_EQ(ref.length(), 0); +} + +TEST(StringViewTest, CStringInitialization) +{ + const char *val = "hello world"; + + string_view ref(val); + + EXPECT_EQ(ref.data(), val); + EXPECT_EQ(ref.length(), std::strlen(val)); +} + +TEST(StringViewTest, StdStringInitialization) +{ + const std::string val = "hello world"; + + string_view ref(val); + + EXPECT_EQ(ref.data(), val.data()); + EXPECT_EQ(ref.length(), val.size()); +} + +TEST(StringViewTest, Copy) +{ + const std::string val = "hello world"; + + string_view ref(val); + string_view cpy(ref); + + EXPECT_EQ(cpy.data(), val); + EXPECT_EQ(cpy.length(), val.length()); + EXPECT_EQ(cpy, val); +} + +TEST(StringViewTest, Accessor) +{ + string_view s = "abc123"; + EXPECT_EQ(s.data(), &s[0]); + EXPECT_EQ(s.data() + 1, &s[1]); +} + +TEST(StringViewTest, ExplicitStdStringConversion) +{ + std::string s = static_cast(string_view{"abc"}); + EXPECT_EQ(s, "abc"); +} + +TEST(StringViewTest, SubstrPortion) +{ + string_view s = "abc123"; + EXPECT_EQ("123", s.substr(3)); + EXPECT_EQ("12", s.substr(3, 2)); +} + +TEST(StringViewTest, SubstrOutOfRange) +{ + string_view s = "abc123"; +#if __EXCEPTIONS || defined(HAVE_CPP_STDLIB) + EXPECT_THROW(s.substr(10), std::out_of_range); +#else + EXPECT_DEATH({ s.substr(10); }, ""); +#endif +} + +TEST(StringViewTest, FindSingleCharacter) +{ + string_view s = "abc"; + + // starting from 0-th position (default) + EXPECT_EQ(s.find('a'), 0); + EXPECT_EQ(s.find('b'), 1); + EXPECT_EQ(s.find('c'), 2); + EXPECT_EQ(s.find('d'), -1); // FIXME: string_view:npos - problem with linker + + // starting from given index + EXPECT_EQ(s.find('a', 1), -1); + EXPECT_EQ(s.find('b', 1), 1); + + // out of index + EXPECT_EQ(s.find('a', 10), -1); +} + +TEST(StringViewTest, Compare) +{ + string_view s1 = "aaa"; + string_view s2 = "bbb"; + string_view s3 = "aaa"; + + // Equals + EXPECT_EQ(s1, s3); + EXPECT_EQ(s1, s1); + + // Less then + EXPECT_LT(s1, s2); + + // Greater then + EXPECT_GT(s2, s1); +} + +TEST(StringViewTest, MapKeyOrdering) +{ + std::map m = {{"bbb", 2}, {"aaa", 1}, {"ccc", 3}}; + size_t i = 1; + for (const auto &kv : m) + { + EXPECT_EQ(kv.second, i); + i++; + } +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/unique_ptr_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/unique_ptr_test.cc new file mode 100644 index 000000000..1d2e6c062 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/unique_ptr_test.cc @@ -0,0 +1,169 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/unique_ptr.h" + +#include + +using opentelemetry::nostd::unique_ptr; + +class A +{ +public: + explicit A(bool &destructed) noexcept : destructed_{destructed} { destructed_ = false; } + + ~A() { destructed_ = true; } + +private: + bool &destructed_; +}; + +class B +{ +public: + int f() const { return 123; } +}; + +TEST(UniquePtrTest, DefaultConstruction) +{ + unique_ptr ptr1; + EXPECT_EQ(ptr1.get(), nullptr); + + unique_ptr ptr2{nullptr}; + EXPECT_EQ(ptr2.get(), nullptr); +} + +TEST(UniquePtrTest, ExplicitConstruction) +{ + auto value = new int{123}; + unique_ptr ptr1{value}; + EXPECT_EQ(ptr1.get(), value); + + auto array = new int[5]; + unique_ptr ptr2{array}; + EXPECT_EQ(ptr2.get(), array); +} + +TEST(UniquePtrTest, MoveConstruction) +{ + auto value = new int{123}; + unique_ptr ptr1{value}; + unique_ptr ptr2{std::move(ptr1)}; + EXPECT_EQ(ptr1.get(), nullptr); + EXPECT_EQ(ptr2.get(), value); +} + +TEST(UniquePtrTest, MoveConstructionFromDifferentType) +{ + auto value = new int{123}; + unique_ptr ptr1{value}; + unique_ptr ptr2{std::move(ptr1)}; + EXPECT_EQ(ptr1.get(), nullptr); + EXPECT_EQ(ptr2.get(), value); +} + +TEST(UniquePtrTest, MoveConstructionFromStdUniquePtr) +{ + auto value = new int{123}; + std::unique_ptr ptr1{value}; + unique_ptr ptr2{std::move(ptr1)}; + EXPECT_EQ(ptr1.get(), nullptr); + EXPECT_EQ(ptr2.get(), value); +} + +TEST(UniquePtrTest, Destruction) +{ + bool was_destructed; + unique_ptr{new A{was_destructed}}; + EXPECT_TRUE(was_destructed); +} + +TEST(UniquePtrTest, StdUniquePtrConversionOperator) +{ + auto value = new int{123}; + unique_ptr ptr1{value}; + std::unique_ptr ptr2{std::move(ptr1)}; + EXPECT_EQ(ptr1.get(), nullptr); + EXPECT_EQ(ptr2.get(), value); + + value = new int{456}; + ptr1 = unique_ptr{value}; + ptr2 = std::move(ptr1); + EXPECT_EQ(ptr1.get(), nullptr); + EXPECT_EQ(ptr2.get(), value); + + ptr2 = nullptr; + EXPECT_EQ(ptr2.get(), nullptr); + + EXPECT_TRUE((std::is_assignable, unique_ptr &&>::value)); + EXPECT_FALSE((std::is_assignable, unique_ptr &>::value)); +} + +TEST(UniquePtrTest, BoolConversionOpertor) +{ + auto value = new int{123}; + unique_ptr ptr1{value}; + + EXPECT_TRUE(ptr1); + EXPECT_FALSE(unique_ptr{}); +} + +TEST(UniquePtrTest, PointerOperators) +{ + auto value = new int{123}; + unique_ptr ptr1{value}; + + EXPECT_EQ(&*ptr1, value); + EXPECT_EQ( + unique_ptr { new B }->f(), 123); +} + +TEST(UniquePtrTest, Reset) +{ + bool was_destructed1; + unique_ptr ptr{new A{was_destructed1}}; + bool was_destructed2; + ptr.reset(new A{was_destructed2}); + EXPECT_TRUE(was_destructed1); + EXPECT_FALSE(was_destructed2); + ptr.reset(); + EXPECT_TRUE(was_destructed2); +} + +TEST(UniquePtrTest, Release) +{ + auto value = new int{123}; + unique_ptr ptr{value}; + EXPECT_EQ(ptr.release(), value); + EXPECT_EQ(ptr.get(), nullptr); + delete value; +} + +TEST(UniquePtrTest, Swap) +{ + auto value1 = new int{123}; + unique_ptr ptr1{value1}; + + auto value2 = new int{456}; + unique_ptr ptr2{value2}; + ptr1.swap(ptr2); + + EXPECT_EQ(ptr1.get(), value2); + EXPECT_EQ(ptr2.get(), value1); +} + +TEST(UniquePtrTest, Comparison) +{ + unique_ptr ptr1{new int{123}}; + unique_ptr ptr2{new int{456}}; + unique_ptr ptr3{}; + + EXPECT_EQ(ptr1, ptr1); + EXPECT_NE(ptr1, ptr2); + + EXPECT_NE(ptr1, nullptr); + EXPECT_NE(nullptr, ptr1); + + EXPECT_EQ(ptr3, nullptr); + EXPECT_EQ(nullptr, ptr3); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/utility_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/utility_test.cc new file mode 100644 index 000000000..821b2a70a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/utility_test.cc @@ -0,0 +1,56 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/utility.h" + +#include +#include +#include + +#include + +namespace nostd = opentelemetry::nostd; + +template +auto IsDataCallable(const T &t) -> decltype(nostd::data(t), std::true_type{}); + +std::false_type IsDataCallable(...); + +template +auto IsSizeCallable(const T &t) -> decltype(nostd::size(t), std::true_type{}); + +std::false_type IsSizeCallable(...); + +TEST(UtilityTest, Data) +{ + std::vector v = {1, 2, 3}; + int array[3] = {1, 2, 3}; + std::initializer_list list{1, 2, 3}; + int x = 0; + std::ignore = x; + + EXPECT_EQ(nostd::data(v), v.data()); + EXPECT_EQ(nostd::data(array), array); + EXPECT_EQ(nostd::data(list), list.begin()); + EXPECT_FALSE(decltype(IsDataCallable(x)){}); +} + +TEST(UtilityTest, Size) +{ + std::vector v = {1, 2, 3}; + int array[3] = {1, 2, 3}; + int x = 0; + std::ignore = x; + + EXPECT_EQ(nostd::size(v), v.size()); + EXPECT_EQ(nostd::size(array), 3); + + EXPECT_FALSE(decltype(IsSizeCallable(x)){}); +} + +TEST(UtilityTest, MakeIndexSequence) +{ + EXPECT_TRUE((std::is_same, nostd::index_sequence<>>::value)); + EXPECT_TRUE((std::is_same, nostd::index_sequence<0>>::value)); + EXPECT_TRUE((std::is_same, nostd::index_sequence<0, 1>>::value)); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/nostd/variant_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/variant_test.cc new file mode 100644 index 000000000..cea5c4ee7 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/nostd/variant_test.cc @@ -0,0 +1,119 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/variant.h" + +#include +#include + +#include + +namespace nostd = opentelemetry::nostd; + +class DestroyCounter +{ +public: + explicit DestroyCounter(int *count) : count_{count} {} + ~DestroyCounter() { ++*count_; } + +private: + int *count_; +}; + +TEST(VariantSizeTest, GetVariantSize) +{ + EXPECT_EQ(nostd::variant_size>::value, 0); + EXPECT_EQ(nostd::variant_size>::value, 1); + EXPECT_EQ((nostd::variant_size>::value), 2); +} + +#if 0 // Disable this test for now. It does not compile with Visual Studio 2015. +TEST(VariantAlternativeTest, GetVariantSize) +{ + EXPECT_TRUE((std::is_same>, int>::value)); + EXPECT_TRUE( + (std::is_same>, double>::value)); + EXPECT_TRUE((std::is_same>, + const double>::value)); +} +#endif + +TEST(VariantTest, Get) +{ + nostd::variant v, w; + v = 12; + EXPECT_EQ(nostd::get(v), 12); + EXPECT_EQ(nostd::get<0>(v), 12); + w = v; + EXPECT_EQ(nostd::get(w), 12); + EXPECT_EQ(*nostd::get_if(&v), 12); + EXPECT_EQ(nostd::get_if(&v), nullptr); +#if __EXCEPTIONS + EXPECT_THROW(nostd::get(w), nostd::bad_variant_access); +#else + EXPECT_DEATH({ nostd::get(w); }, ""); +#endif +} + +TEST(VariantTest, Comparison) +{ + nostd::variant v, w; + EXPECT_TRUE(v == w); + EXPECT_FALSE(v != w); + v = 3.0f; + EXPECT_TRUE(v != w); + EXPECT_FALSE(v == w); + v = 2; + w = 3; + EXPECT_TRUE(v != w); + EXPECT_FALSE(v == w); + EXPECT_TRUE(v < w); + EXPECT_FALSE(v > w); +} + +TEST(VariantTest, Visit) +{ + nostd::variant v; + struct + { + int operator()(int) { return 0; } + int operator()(float) { return 1; } + } a; + EXPECT_EQ(nostd::visit(a, v), 0); + v = 2.0f; + EXPECT_EQ(nostd::visit(a, v), 1); +} + +TEST(VariantTest, Destructor) +{ + nostd::variant v; + int destroy_count = 0; + v = DestroyCounter{&destroy_count}; + destroy_count = 0; + v = 1; + EXPECT_EQ(destroy_count, 1); + { + nostd::variant w; + w = DestroyCounter{&destroy_count}; + destroy_count = 0; + } + EXPECT_EQ(destroy_count, 1); +} + +TEST(VariantTest, Conversion) +{ + nostd::variant x("abc"); + x = "def"; + EXPECT_EQ(nostd::get(x), "def"); + + nostd::variant y("abc"); + EXPECT_TRUE(nostd::holds_alternative(y)); + y = std::string{"xyz"}; + EXPECT_TRUE(nostd::holds_alternative(y)); +} + +TEST(VariantTest, Construction) +{ + nostd::variant v{"abc"}; + EXPECT_EQ(v.index(), 1); +} diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/plugin/BUILD b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/BUILD new file mode 100644 index 000000000..98e3679b3 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/BUILD @@ -0,0 +1,17 @@ +cc_test( + name = "dynamic_load_test", + srcs = [ + "dynamic_load_test.cc", + ], + linkopts = [ + "-ldl", + ], + tags = [ + "api", + "test", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/plugin/CMakeLists.txt b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/CMakeLists.txt new file mode 100644 index 000000000..6bdcbf9c3 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/CMakeLists.txt @@ -0,0 +1,10 @@ +include(GoogleTest) + +add_executable(dynamic_load_test dynamic_load_test.cc) +target_link_libraries(dynamic_load_test ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) +target_link_libraries(dynamic_load_test ${CMAKE_DL_LIBS}) +gtest_add_tests( + TARGET dynamic_load_test + TEST_PREFIX plugin. + TEST_LIST dynamic_load_test) diff --git a/src/jaegertracing/opentelemetry-cpp/api/test/plugin/dynamic_load_test.cc b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/dynamic_load_test.cc new file mode 100644 index 000000000..4fdc79eee --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/test/plugin/dynamic_load_test.cc @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/plugin/dynamic_load.h" + +#include + +TEST(LoadFactoryTest, FailureTest) +{ + std::string error_message; + auto factory = opentelemetry::plugin::LoadFactory("no-such-plugin", error_message); + EXPECT_EQ(factory, nullptr); + EXPECT_FALSE(error_message.empty()); +} 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 +#include + +#include + +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 +#include +#include "opentelemetry/nostd/type_traits.h" + +using namespace opentelemetry; + +static int TakeKeyValues(const common::KeyValueIterable &iterable) +{ + std::map result; + int count = 0; + iterable.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { + ++count; + return true; + }); + return count; +} + +template ::value> * = nullptr> +static int TakeKeyValues(const T &iterable) +{ + return TakeKeyValues(common::KeyValueIterableView{iterable}); +} + +TEST(KeyValueIterableViewTest, is_key_value_iterable) +{ + using M1 = std::map; + EXPECT_TRUE(bool{common::detail::is_key_value_iterable::value}); + + using M2 = std::map; + EXPECT_TRUE(bool{common::detail::is_key_value_iterable::value}); + + using M3 = std::map; + EXPECT_TRUE(bool{common::detail::is_key_value_iterable::value}); + + struct A + {}; + using M4 = std::map; + EXPECT_FALSE(bool{common::detail::is_key_value_iterable::value}); +} + +TEST(KeyValueIterableViewTest, ForEachKeyValue) +{ + std::map m1 = {{"abc", "123"}, {"xyz", "456"}}; + EXPECT_EQ(TakeKeyValues(m1), 2); + + std::vector> v1 = {{"abc", 123}, {"xyz", 456}}; + EXPECT_EQ(TakeKeyValues(v1), 2); +} + +TEST(KeyValueIterableViewTest, ForEachKeyValueWithExit) +{ + using M = std::map; + M m1 = {{"abc", "123"}, {"xyz", "456"}}; + common::KeyValueIterableView 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 +#include +#include + +#include + +namespace trace_api = opentelemetry::trace; +namespace nonstd = opentelemetry::nostd; +namespace common = opentelemetry::common; + +TEST(NoopTest, UseNoopTracers) +{ + std::shared_ptr tracer{new trace_api::NoopTracer{}}; + auto s1 = tracer->StartSpan("abc"); + + std::map attributes1; + s1->AddEvent("abc", attributes1); + + std::vector> attributes2; + s1->AddEvent("abc", attributes2); + + s1->AddEvent("abc", {{"a", 1}, {"b", "2"}, {"c", 3.0}}); + + std::vector>> 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 tracer{new trace_api::NoopTracer{}}; + + std::map attrs = {{"a", "3"}}; + std::vector>> 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( + new trace_api::SpanContext{trace_id, span_id, trace_api::TraceFlags{true}, false}); + std::shared_ptr tracer{new trace_api::NoopTracer{}}; + auto s1 = + nonstd::shared_ptr(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 + +#include + +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 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(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>(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>(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>(ctx2_span)); + + auto span = nostd::get>(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>(ctx2_span)); + + auto span = nostd::get>(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>(ctx2_span)); + + auto span = nostd::get>(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>(ctx2_span)); + + auto span = nostd::get>(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 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 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 +#include + +#include + +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 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(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(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(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>(ctx2_span)); + + auto span = nostd::get>(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 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 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(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(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(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 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 + +#include + +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 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 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 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 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 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(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 + +template +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 + +using opentelemetry::trace::Provider; +using opentelemetry::trace::Tracer; +using opentelemetry::trace::TracerProvider; + +namespace nostd = opentelemetry::nostd; + +class TestProvider : public TracerProvider +{ + nostd::shared_ptr GetTracer(nostd::string_view library_name, + nostd::string_view library_version, + nostd::string_view schema_url) noexcept override + { + return nostd::shared_ptr(nullptr); + } +}; + +TEST(Provider, GetTracerProviderDefault) +{ + auto tf = Provider::GetTracerProvider(); + EXPECT_NE(nullptr, tf); +} + +TEST(Provider, SetTracerProvider) +{ + auto tf = nostd::shared_ptr(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 + +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(new NoopSpan(nullptr)); + Scope scope(span); + + context::ContextValue active_span_value = context::RuntimeContext::GetValue(kSpanKey); + ASSERT_TRUE(nostd::holds_alternative>(active_span_value)); + + auto active_span = nostd::get>(active_span_value); + ASSERT_EQ(active_span, span); +} + +TEST(ScopeTest, Destruct) +{ + nostd::shared_ptr span(new NoopSpan(nullptr)); + Scope scope(span); + + { + nostd::shared_ptr span_nested(new NoopSpan(nullptr)); + Scope scope_nested(span_nested); + + context::ContextValue active_span_value = context::RuntimeContext::GetValue(kSpanKey); + ASSERT_TRUE(nostd::holds_alternative>(active_span_value)); + + auto active_span = nostd::get>(active_span_value); + ASSERT_EQ(active_span, span_nested); + } + + context::ContextValue active_span_value = context::RuntimeContext::GetValue(kSpanKey); + ASSERT_TRUE(nostd::holds_alternative>(active_span_value)); + + auto active_span = nostd::get>(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 + +#include + +using opentelemetry::trace::SpanContext; +namespace trace_api = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; +namespace context = opentelemetry::context; + +namespace +{ + +std::shared_ptr initTracer() +{ + return std::shared_ptr(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( + 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(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 + +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 +#include + +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 +#include + +#include + +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 +#include + +#include + +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 +#include + +#include + +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 +#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 + +namespace trace_api = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; +namespace context = opentelemetry::context; + +TEST(TracerTest, GetCurrentSpan) +{ + std::unique_ptr tracer(new trace_api::NoopTracer()); + nostd::shared_ptr span_first(new trace_api::NoopSpan(nullptr)); + nostd::shared_ptr 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()); +} -- cgit v1.2.3