From 5efc5f66685704c1bce398455def3c093fcee606 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Sun, 29 Oct 2023 15:01:04 +0100 Subject: [PATCH] Add grpc metric unit tests --- exporters/otlp/BUILD | 16 ++ exporters/otlp/CMakeLists.txt | 14 ++ .../otlp/otlp_grpc_metric_exporter.h | 2 +- .../test/otlp_grpc_metric_exporter_test.cc | 209 ++++++++++++++++++ 4 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 exporters/otlp/test/otlp_grpc_metric_exporter_test.cc diff --git a/exporters/otlp/BUILD b/exporters/otlp/BUILD index 3bbbcd7d6a..a70153edd8 100644 --- a/exporters/otlp/BUILD +++ b/exporters/otlp/BUILD @@ -444,6 +444,22 @@ cc_test( ], ) +cc_test( + name = "otlp_grpc_metric_exporter_test", + srcs = ["test/otlp_grpc_metric_exporter_test.cc"], + tags = [ + "otlp", + "otlp_grpc_metric", + "test", + ], + deps = [ + ":otlp_grpc_metric_exporter", + "//api", + "//sdk/src/metrics", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "otlp_grpc_metric_exporter_factory_test", srcs = ["test/otlp_grpc_metric_exporter_factory_test.cc"], diff --git a/exporters/otlp/CMakeLists.txt b/exporters/otlp/CMakeLists.txt index 0b7814093b..2f972e0744 100644 --- a/exporters/otlp/CMakeLists.txt +++ b/exporters/otlp/CMakeLists.txt @@ -303,6 +303,20 @@ if(BUILD_TESTING) TEST_PREFIX exporter.otlp. TEST_LIST otlp_grpc_log_record_exporter_factory_test) + add_executable(otlp_grpc_metric_exporter_test + test/otlp_grpc_metric_exporter_test.cc) + target_link_libraries( + otlp_grpc_metric_exporter_test + ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${GMOCK_LIB} + opentelemetry_exporter_otlp_grpc + opentelemetry_exporter_otlp_grpc_metrics) + gtest_add_tests( + TARGET otlp_grpc_metric_exporter_test + TEST_PREFIX exporter.otlp. + TEST_LIST otlp_grpc_metric_exporter_test) + add_executable(otlp_grpc_metric_exporter_factory_test test/otlp_grpc_metric_exporter_factory_test.cc) target_link_libraries( diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h index 11bb64c24f..5f975c8ce3 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h @@ -63,7 +63,7 @@ class OtlpGrpcMetricExporter : public opentelemetry::sdk::metrics::PushMetricExp const sdk::metrics::AggregationTemporalitySelector aggregation_temporality_selector_; // For testing - friend class OtlpGrpcExporterTestPeer; + friend class OtlpGrpcMetricExporterTestPeer; // Store service stub internally. Useful for testing. std::unique_ptr diff --git a/exporters/otlp/test/otlp_grpc_metric_exporter_test.cc b/exporters/otlp/test/otlp_grpc_metric_exporter_test.cc new file mode 100644 index 0000000000..dc6dde9d79 --- /dev/null +++ b/exporters/otlp/test/otlp_grpc_metric_exporter_test.cc @@ -0,0 +1,209 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTELEMETRY_STL_VERSION +// Unfortunately as of 04/27/2021 the fix is NOT in the vcpkg snapshot of Google Test. +// Remove above `#ifdef` once the GMock fix for C++20 is in the mainline. +// +// Please refer to this GitHub issue for additional details: +// https://github.com/google/googletest/issues/2914 +// https://github.com/google/googletest/commit/61f010d703b32de9bfb20ab90ece38ab2f25977f +// +// If we compile using Visual Studio 2019 with `c++latest` (C++20) without the GMock fix, +// then the compilation here fails in `gmock-actions.h` from: +// .\tools\vcpkg\installed\x64-windows\include\gmock\gmock-actions.h(819): +// error C2653: 'result_of': is not a class or namespace name +// +// That is because `std::result_of` has been removed in C++20. + +# include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h" + +# include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" + +// Problematic code that pulls in Gmock and breaks with vs2019/c++latest : +# include "opentelemetry/proto/collector/metrics/v1/metrics_service_mock.grpc.pb.h" + +# include "opentelemetry/exporters/otlp/protobuf_include_suffix.h" + +# include "opentelemetry/sdk/trace/simple_processor.h" +# include "opentelemetry/sdk/trace/tracer_provider.h" +# include "opentelemetry/trace/provider.h" + +# include + +# if defined(_MSC_VER) +# include "opentelemetry/sdk/common/env_variables.h" +using opentelemetry::sdk::common::setenv; +using opentelemetry::sdk::common::unsetenv; +# endif + +using namespace testing; + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +class OtlpGrpcMetricExporterTestPeer : public ::testing::Test +{ +public: + std::unique_ptr GetExporter( + std::unique_ptr &stub_interface) + { + return std::unique_ptr( + new OtlpGrpcMetricExporter(std::move(stub_interface))); + } + + // Get the options associated with the given exporter. + const OtlpGrpcMetricExporterOptions &GetOptions(std::unique_ptr &exporter) + { + return exporter->options_; + } +}; + +// Test exporter configuration options +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigTest) +{ + OtlpGrpcMetricExporterOptions opts; + opts.endpoint = "localhost:45454"; + std::unique_ptr exporter(new OtlpGrpcMetricExporter(opts)); + EXPECT_EQ(GetOptions(exporter).endpoint, "localhost:45454"); +} + +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigSslCredentialsTest) +{ + std::string cacert_str = "--begin and end fake cert--"; + OtlpGrpcMetricExporterOptions opts; + opts.use_ssl_credentials = true; + opts.ssl_credentials_cacert_as_string = cacert_str; + std::unique_ptr exporter(new OtlpGrpcMetricExporter(opts)); + EXPECT_EQ(GetOptions(exporter).ssl_credentials_cacert_as_string, cacert_str); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); +} + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigFromEnv) +{ + const std::string cacert_str = "--begin and end fake cert--"; + setenv("OTEL_EXPORTER_OTLP_CERTIFICATE_STRING", cacert_str.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_SSL_ENABLE", "True", 1); + const std::string endpoint = "https://localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_TIMEOUT", "20050ms", 1); + setenv("OTEL_EXPORTER_OTLP_HEADERS", "k1=v1,k2=v2", 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_HEADERS", "k1=v3,k1=v4", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).ssl_credentials_cacert_as_string, cacert_str); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + EXPECT_EQ(GetOptions(exporter).timeout.count(), + std::chrono::duration_cast( + std::chrono::milliseconds{20050}) + .count()); + EXPECT_EQ(GetOptions(exporter).metadata.size(), 3); + { + // Test k2 + auto range = GetOptions(exporter).metadata.equal_range("k2"); + EXPECT_TRUE(range.first != range.second); + EXPECT_EQ(range.first->second, std::string("v2")); + ++range.first; + EXPECT_TRUE(range.first == range.second); + } + { + // Test k1 + auto range = GetOptions(exporter).metadata.equal_range("k1"); + EXPECT_TRUE(range.first != range.second); + EXPECT_EQ(range.first->second, std::string("v3")); + ++range.first; + EXPECT_EQ(range.first->second, std::string("v4")); + ++range.first; + EXPECT_TRUE(range.first == range.second); + } + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_CERTIFICATE_STRING"); + unsetenv("OTEL_EXPORTER_OTLP_SSL_ENABLE"); + unsetenv("OTEL_EXPORTER_OTLP_TIMEOUT"); + unsetenv("OTEL_EXPORTER_OTLP_HEADERS"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_HEADERS"); +} +# endif + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigHttpsSecureFromEnv) +{ + // https takes precedence over insecure + const std::string endpoint = "https://localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE", "true", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE"); +} +# endif + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigHttpInsecureFromEnv) +{ + // http takes precedence over secure + const std::string endpoint = "http://localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE", "false", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, false); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE"); +} +# endif + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigUnknownSecureFromEnv) +{ + const std::string endpoint = "localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE", "false", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE"); +} +# endif + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigUnknownInsecureFromEnv) +{ + const std::string endpoint = "localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE", "true", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, false); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE"); +} +# endif + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE +#endif /* OPENTELEMETRY_STL_VERSION */