diff --git a/sdk/core/azure-core/test/perf/CMakeLists.txt b/sdk/core/azure-core/test/perf/CMakeLists.txt index 4f962c16d7..5b54701048 100644 --- a/sdk/core/azure-core/test/perf/CMakeLists.txt +++ b/sdk/core/azure-core/test/perf/CMakeLists.txt @@ -11,6 +11,7 @@ set( AZURE_CORE_PERF_TEST_HEADER inc/azure/core/test/http_transport_test.hpp inc/azure/core/test/nullable_test.hpp + inc/azure/core/test/pipeline_test.hpp inc/azure/core/test/uuid_test.hpp ) diff --git a/sdk/core/azure-core/test/perf/inc/azure/core/test/pipeline_test.hpp b/sdk/core/azure-core/test/perf/inc/azure/core/test/pipeline_test.hpp new file mode 100644 index 0000000000..18e0cce9dc --- /dev/null +++ b/sdk/core/azure-core/test/perf/inc/azure/core/test/pipeline_test.hpp @@ -0,0 +1,200 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @file + * @brief Test the HTTP send performance. + * + */ + +#pragma once + +#include "../../../core/perf/inc/azure/perf.hpp" + +#include +#include +#include + +#include +#include +using namespace Azure::Core; +using namespace Azure::Core::_internal; +using namespace Azure::Core::Http; +using namespace Azure::Core::Http::_internal; +using namespace Azure::Core::Http::Policies; +using namespace Azure::Core::Http::Policies::_internal; + +namespace Azure { namespace Core { namespace Test { + + class TestPolicy : public HttpPolicy { + + public: + std::unique_ptr Clone() const override + { + return std::make_unique(*this); + } + + std::unique_ptr Send( + Request& request, + NextHttpPolicy nextPolicy, + Context const& context) const override + { + return nextPolicy.Send(request, context); + }; + }; + + /** + * @brief Measure the http pipeline / policies performance. + */ + class PipelineTest : public Azure::Perf::PerfTest { + std::unique_ptr m_pipeline; + + static std::vector SplitString(const std::string& s, char separator) + { + std::vector result; + + const auto len = s.size(); + size_t start = 0; + while (start < len) + { + auto end = s.find(separator, start); + if (end == std::string::npos) + { + end = len; + } + + result.push_back(s.substr(start, end - start)); + + start = end + 1; + } + + return result; + } + + public: + /** + * @brief Construct a new PipelineTest test. + * + * @param options The test options. + */ + PipelineTest(Azure::Perf::TestOptions options) : PerfTest(options) {} + + void Setup() override + { + const std::string packageName = "test"; + const std::string packageVersion = "1.0.0"; + const std::string testPolicyName = "TestPolicy"; + const std::string retryPolicyName = "RetryPolicy"; + const std::string requestIdPolicyName = "RequestIdPolicy"; + const std::string requestActivityPolicyName = "RequestActivityPolicy"; + const std::string telemetryPolicyName = "TelemetryPolicy"; + const std::string logPolicyName = "LogPolicy"; + + HttpSanitizer httpSanitizer; + + std::vector> policies; + std::vector> policies2; + + auto const total = m_options.GetMandatoryOption("Count"); + auto const policyNames + = SplitString(m_options.GetOptionOrDefault("Policies", "TestPolicy"), ','); + // we want a total number of policies added to the pipeline + // thus for loop total / number , depends on rounding but close enough + // since in each loop we add the whole set of desired policies + // we also get stack overflow with lots of policies since the pipeline is a two level + // recursion + for (int i = 0; i < static_cast(total / policyNames.size()); i++) + { + if (std::find(policyNames.begin(), policyNames.end(), testPolicyName) != policyNames.end()) + { + policies.push_back(std::make_unique()); + policies2.push_back(std::make_unique()); + } + if (std::find(policyNames.begin(), policyNames.end(), retryPolicyName) != policyNames.end()) + { + policies.push_back(std::make_unique(RetryOptions{})); + policies2.push_back(std::make_unique(RetryOptions{})); + } + if (std::find(policyNames.begin(), policyNames.end(), requestIdPolicyName) + != policyNames.end()) + { + policies.push_back(std::make_unique()); + policies2.push_back(std::make_unique()); + } + if (std::find(policyNames.begin(), policyNames.end(), requestActivityPolicyName) + != policyNames.end()) + { + policies.push_back(std::make_unique(httpSanitizer)); + policies2.push_back(std::make_unique(httpSanitizer)); + } + if (std::find(policyNames.begin(), policyNames.end(), telemetryPolicyName) + != policyNames.end()) + { + policies.push_back(std::make_unique(packageName, packageVersion)); + policies2.push_back(std::make_unique(packageName, packageVersion)); + } + if (std::find(policyNames.begin(), policyNames.end(), logPolicyName) != policyNames.end()) + { + policies.push_back(std::make_unique(LogOptions())); + policies2.push_back(std::make_unique(LogOptions())); + } + } + + m_pipeline = std::make_unique( + ClientOptions(), packageName, packageVersion, std::move(policies), std::move(policies2)); + } + + /** + * @brief Executes the pipeline + * + */ + void Run(Context const&) override + { + try + { + Azure::Core::Http::Request request( + HttpMethod::Get, Url("http://127.0.0.1:5000/admin/isalive")); + Context context; + m_pipeline->Send(request, context); + } + catch (std::exception const&) + { + // don't print exceptions, they are happening at each request, this is the point of the test + } + } + + /** + * @brief Define the test options for the test. + * + * @return The list of test options. + */ + std::vector GetTestOptions() override + { + return { + {"Count", {"--count"}, "The number of policy objects to be created.", 1, true}, + {"Policies", + {"--policies"}, + "The policies to be added to the pipeline. Allows multiple values comma separated.\n" + "default:TestPolicy \n others: " + "RetryPolicy,RequestIdPolicy,RequestActivityPolicy,TelemetryPolicy,LogPolicy", + 1, + false}}; + } + + /** + * @brief Get the static Test Metadata for the test. + * + * @return Azure::Perf::TestMetadata describing the test. + */ + static Azure::Perf::TestMetadata GetTestMetadata() + { + return { + "PipelineBaseTest", + "Measures HTTP pipeline and policies performance", + [](Azure::Perf::TestOptions options) { + return std::make_unique(options); + }}; + } + }; + +}}} // namespace Azure::Core::Test diff --git a/sdk/core/azure-core/test/perf/src/azure_core_perf_test.cpp b/sdk/core/azure-core/test/perf/src/azure_core_perf_test.cpp index 7ea82309ba..224f97d546 100644 --- a/sdk/core/azure-core/test/perf/src/azure_core_perf_test.cpp +++ b/sdk/core/azure-core/test/perf/src/azure_core_perf_test.cpp @@ -3,6 +3,7 @@ #include "azure/core/test/http_transport_test.hpp" #include "azure/core/test/nullable_test.hpp" +#include "azure/core/test/pipeline_test.hpp" #include "azure/core/test/uuid_test.hpp" #include @@ -16,6 +17,7 @@ int main(int argc, char** argv) std::vector tests{ Azure::Core::Test::HTTPTransportTest::GetTestMetadata(), Azure::Core::Test::NullableTest::GetTestMetadata(), + Azure::Core::Test::PipelineTest::GetTestMetadata(), Azure::Core::Test::UuidTest::GetTestMetadata()}; Azure::Perf::Program::Run(Azure::Core::Context::ApplicationContext, tests, argc, argv);