From 4cba4eb3f122c7a1a49b629b1c0656d7f817f001 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Fri, 24 Oct 2025 19:32:01 +0200 Subject: move cpr in-tree (#605) * added cpr 1.10.5 in-tree to allow updates to vcpkg without breaking the build * added asio 1.29.0 in-tree to remove one more vcpkg dependency * bumped vcpkg to 2024.06.15 to address failure to build due to use of deprecated binaries in vcpkg (404 error: `https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-pkgconf-1~2.1.0-1-any.pkg.tar.zst` during build) --- thirdparty/cpr/test/interceptor_multi_tests.cpp | 470 ++++++++++++++++++++++++ 1 file changed, 470 insertions(+) create mode 100644 thirdparty/cpr/test/interceptor_multi_tests.cpp (limited to 'thirdparty/cpr/test/interceptor_multi_tests.cpp') diff --git a/thirdparty/cpr/test/interceptor_multi_tests.cpp b/thirdparty/cpr/test/interceptor_multi_tests.cpp new file mode 100644 index 000000000..28a0af573 --- /dev/null +++ b/thirdparty/cpr/test/interceptor_multi_tests.cpp @@ -0,0 +1,470 @@ +#include +#include +#include + +#include "cpr/cpr.h" +#include "cpr/interceptor.h" +#include "cpr/response.h" +#include "cpr/session.h" +#include "httpServer.hpp" + +using namespace cpr; + +static HttpServer* server = new HttpServer(); + +class HiddenHelloWorldRedirectInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + std::shared_ptr session = multi.GetSessions().front().first; + + // Save original url + Url old_url = session->GetFullRequestUrl(); + + // Rewrite the url + Url url{server->GetBaseUrl() + "/hello.html"}; + session->SetUrl(url); + + // Proceed the chain + std::vector response = proceed(multi); + EXPECT_FALSE(response.empty()); + + // Restore the url again + response.front().url = old_url; + return response; + } +}; + +class ChangeStatusCodeInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + std::shared_ptr session = multi.GetSessions().front().first; + + // Proceed the chain + std::vector response = proceed(multi); + EXPECT_FALSE(response.empty()); + + // Change the status code + response.front().status_code = 12345; + return response; + } +}; + +class SetBasicAuthInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + std::shared_ptr session = multi.GetSessions().front().first; + + // Set authentication + session->SetAuth(Authentication{"user", "password", AuthMode::BASIC}); + + // Proceed the chain + return proceed(multi); + } +}; + +class SetUnsupportedProtocolErrorInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + std::shared_ptr session = multi.GetSessions().front().first; + + // Proceed the chain + std::vector response = proceed(multi); + EXPECT_FALSE(response.empty()); + + // Set unsupported protocol error + response.front().error = Error{CURLE_UNSUPPORTED_PROTOCOL, "SetErrorInterceptorMulti"}; + + // Return response + return response; + } +}; + +class ChangeRequestMethodToGetInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + multi.GetSessions().front().second = MultiPerform::HttpMethod::GET_REQUEST; + + return proceed(multi); + } +}; + +class ChangeRequestMethodToPostInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + multi.GetSessions().front().second = MultiPerform::HttpMethod::POST_REQUEST; + multi.GetSessions().front().first->SetOption(Payload{{"x", "5"}}); + return proceed(multi); + } +}; + +class ChangeRequestMethodToPutInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + multi.GetSessions().front().second = MultiPerform::HttpMethod::PUT_REQUEST; + multi.GetSessions().front().first->SetOption(Payload{{"x", "5"}}); + return proceed(multi); + } +}; + +class ChangeRequestMethodToDeleteInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + multi.GetSessions().front().second = MultiPerform::HttpMethod::DELETE_REQUEST; + return proceed(multi); + } +}; + +bool write_data(std::string /*data*/, intptr_t /*userdata*/) { + return true; +} + +class ChangeRequestMethodToDownloadCallbackInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + multi.GetSessions().front().second = MultiPerform::HttpMethod::DOWNLOAD_REQUEST; + PrepareDownloadSession(multi, 0, WriteCallback{write_data, 0}); + return proceed(multi); + } +}; + +class ChangeRequestMethodToHeadInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + multi.GetSessions().front().second = MultiPerform::HttpMethod::HEAD_REQUEST; + return proceed(multi); + } +}; + +class ChangeRequestMethodToOptionsInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + multi.GetSessions().front().second = MultiPerform::HttpMethod::OPTIONS_REQUEST; + return proceed(multi); + } +}; + +class ChangeRequestMethodToPatchInterceptorMulti : public InterceptorMulti { + public: + std::vector intercept(MultiPerform& multi) override { + EXPECT_FALSE(multi.GetSessions().empty()); + multi.GetSessions().front().second = MultiPerform::HttpMethod::PATCH_REQUEST; + multi.GetSessions().front().first->SetOption(Payload{{"x", "5"}}); + return proceed(multi); + } +}; + +TEST(InterceptorMultiTest, HiddenUrlRewriteInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/basic.json"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{"Hello world!"}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeStatusCodeInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/hello.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + long expected_status_code{12345}; + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(expected_status_code, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, DownloadChangeStatusCodeInterceptorMultiTest) { + cpr::Url url{server->GetBaseUrl() + "/download_gzip.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + session->SetHeader(cpr::Header{{"Accept-Encoding", "gzip"}}); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Download(cpr::WriteCallback{write_data, 0}); + EXPECT_EQ(response.size(), 1); + + long expected_status_code{12345}; + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(expected_status_code, response.front().status_code); + EXPECT_EQ(cpr::ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, SetBasicAuthInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/basic_auth.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{"Header reflect GET"}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"text/html"}, response.front().header["content-type"]); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, SetUnsupportedProtocolErrorInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/hello.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_error_message{"SetErrorInterceptorMulti"}; + ErrorCode expected_error_code{ErrorCode::UNSUPPORTED_PROTOCOL}; + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"text/html"}, response.front().header["content-type"]); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(expected_error_message, response.front().error.message); + EXPECT_EQ(expected_error_code, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToGetInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/hello.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Head(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{"Hello world!"}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"text/html"}, response.front().header["content-type"]); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToPostInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/url_post.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Head(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{ + "{\n" + " \"x\": 5\n" + "}"}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"application/json"}, response.front().header["content-type"]); + EXPECT_EQ(201, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToPutInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/put.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{ + "{\n" + " \"x\": 5\n" + "}"}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"application/json"}, response.front().header["content-type"]); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToPatchInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/patch.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{ + "{\n" + " \"x\": 5\n" + "}"}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"application/json"}, response.front().header["content-type"]); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToOptionsInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{""}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"GET, POST, PUT, DELETE, PATCH, OPTIONS"}, response.front().header["Access-Control-Allow-Methods"]); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToHeadInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/hello.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + EXPECT_EQ(std::string{}, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"text/html"}, response.front().header["content-type"]); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToDownloadCallbackInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/download_gzip.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + session->SetHeader(cpr::Header{{"Accept-Encoding", "gzip"}}); + session->SetTimeout(Timeout{2000}); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Put(); + EXPECT_EQ(response.size(), 1); + + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(cpr::ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToDownloadCallbackInterceptorMultiMixTest) { + Url url{server->GetBaseUrl() + "/download_gzip.html"}; + std::shared_ptr session1 = std::make_shared(); + session1->SetUrl(url); + session1->SetHeader(cpr::Header{{"Accept-Encoding", "gzip"}}); + session1->SetTimeout(Timeout{2000}); + + std::shared_ptr session2 = std::make_shared(); + session2->SetUrl(url); + session2->SetHeader(cpr::Header{{"Accept-Encoding", "gzip"}}); + session2->SetTimeout(Timeout{2000}); + + MultiPerform multi; + multi.AddSession(session1); + multi.AddSession(session2); + // Changes only one of two sessions to download, so it is expected to throw an exception here since we can not mix them. + multi.AddInterceptor(std::make_shared()); + EXPECT_THROW(multi.Put(), std::invalid_argument); +} + +TEST(InterceptorMultiTest, ChangeRequestMethodToDeleteInterceptorMultiTest) { + Url url{server->GetBaseUrl() + "/delete.html"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{"Delete success"}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(std::string{"text/html"}, response.front().header["content-type"]); + EXPECT_EQ(200, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, TwoInterceptorMultisTest) { + Url url{server->GetBaseUrl() + "/basic.json"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{"Hello world!"}; + long expected_status_code{12345}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(expected_status_code, response.front().status_code); + EXPECT_EQ(ErrorCode::OK, response.front().error.code); +} + +TEST(InterceptorMultiTest, ThreeInterceptorMultisTest) { + Url url{server->GetBaseUrl() + "/basic.json"}; + std::shared_ptr session = std::make_shared(); + session->SetUrl(url); + MultiPerform multi; + multi.AddSession(session); + multi.AddInterceptor(std::make_shared()); + multi.AddInterceptor(std::make_shared()); + multi.AddInterceptor(std::make_shared()); + std::vector response = multi.Get(); + EXPECT_EQ(response.size(), 1); + + std::string expected_text{"Hello world!"}; + long expected_status_code{12345}; + std::string expected_error_message{"SetErrorInterceptorMulti"}; + ErrorCode expected_error_code{ErrorCode::UNSUPPORTED_PROTOCOL}; + EXPECT_EQ(expected_text, response.front().text); + EXPECT_EQ(url, response.front().url); + EXPECT_EQ(expected_status_code, response.front().status_code); + EXPECT_EQ(expected_error_message, response.front().error.message); + EXPECT_EQ(expected_error_code, response.front().error.code); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(server); + return RUN_ALL_TESTS(); +} \ No newline at end of file -- cgit v1.2.3