xref: /aosp_15_r20/external/federated-compute/fcp/client/http/testing/test_helpers.h (revision 14675a029014e728ec732f129a32e299b2da0601)
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef FCP_CLIENT_HTTP_TESTING_TEST_HELPERS_H_
17 #define FCP_CLIENT_HTTP_TESTING_TEST_HELPERS_H_
18 
19 #include <functional>
20 #include <memory>
21 #include <string>
22 #include <utility>
23 #include <vector>
24 
25 #include "google/longrunning/operations.pb.h"
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 #include "absl/base/attributes.h"
29 #include "absl/status/status.h"
30 #include "absl/status/statusor.h"
31 #include "fcp/base/monitoring.h"
32 #include "fcp/client/http/http_client.h"
33 
34 namespace fcp {
35 namespace client {
36 namespace http {
37 
38 // A simple `HttpResponse` implementation consisting of a code, headers (which
39 // are returned via the `HttpResponse` interface methods), and an optional
40 // in-memory response body which `MockableHttpClient` can use to return the data
41 // via the `HttpRequestCallback::OnResponseBody` method.
42 class FakeHttpResponse : public HttpResponse {
43  public:
FakeHttpResponse(int code,HeaderList headers)44   FakeHttpResponse(int code, HeaderList headers)
45       : code_(code), headers_(headers), body_("") {}
FakeHttpResponse(int code,HeaderList headers,std::string body)46   FakeHttpResponse(int code, HeaderList headers, std::string body)
47       : code_(code), headers_(headers), body_(body) {}
48 
code()49   int code() const override { return code_; }
headers()50   const HeaderList& headers() const override { return headers_; }
body()51   const std::string& body() const { return body_; }
52 
53  private:
54   const int code_;
55   const HeaderList headers_;
56   const std::string body_;
57 };
58 
59 // A simplified version of the `HttpClient` interface for use in tests. Enables
60 // easy use with gMock via the simplified `PerformSingleRequest` interface.
61 class MockableHttpClient : public HttpClient {
62  public:
63   // A simple container holding all important properties of an incoming
64   // `HttpRequest`. This is the parameter type passed to `PerformSingleRequest`,
65   // and because it is a simple struct (as opposed to `HttpRequest`, which uses
66   // a number of methods that are hard to mock such as `HttpRequest::ReadBody`)
67   // it makes it easy to use gMock matchers to match against parts or all of the
68   // request's properties.
69   struct SimpleHttpRequest {
70     const std::string uri;
71     const HttpRequest::Method method;
72     const HeaderList headers;
73     const std::string body;
74   };
75 
76   MockableHttpClient() = default;
77 
78   ABSL_MUST_USE_RESULT std::unique_ptr<HttpRequestHandle> EnqueueRequest(
79       std::unique_ptr<HttpRequest> request) override;
80 
81   absl::Status PerformRequests(
82       std::vector<std::pair<HttpRequestHandle*, HttpRequestCallback*>> requests)
83       override;
84 
85   // Implement this method (e.g. using gMock's MOCK_METHOD) for a simple way to
86   // mock a single request. See `MockHttpClient` below.
87   virtual absl::StatusOr<FakeHttpResponse> PerformSingleRequest(
88       SimpleHttpRequest request) = 0;
89 
90   // Registers a callback that will be called when any request receives a
91   // `HttpRequestHandle::Cancel` call.
SetCancellationListener(std::function<void ()> listener)92   virtual void SetCancellationListener(std::function<void()> listener) {
93     cancellation_listener_ = listener;
94   }
95 
96   // Returns the (fake) number of bytes that the mock client has sent/received.
97   // This number will match the sum of all `HttpRequestHandle`'s
98   // `TotalSentReceivedBytes()` methods after they were processed by the mock
99   // client.
TotalSentReceivedBytes()100   virtual HttpRequestHandle::SentReceivedBytes TotalSentReceivedBytes() {
101     return sent_received_bytes_;
102   }
103 
104  private:
105   std::function<void()> cancellation_listener_ = []() {};
106 
107   // A running (fake) tally of the number of bytes that have been
108   // downloaded/uploaded so far.
109   HttpRequestHandle::SentReceivedBytes sent_received_bytes_;
110 };
111 
112 // A convenient to use mock HttpClient implementation.
113 class MockHttpClient : public MockableHttpClient {
114  public:
115   MockHttpClient() = default;
116 
117   MOCK_METHOD(absl::StatusOr<FakeHttpResponse>, PerformSingleRequest,
118               (SimpleHttpRequest request), (override));
119 };
120 
121 ::testing::Matcher<MockableHttpClient::SimpleHttpRequest>
122 SimpleHttpRequestMatcher(
123     const ::testing::Matcher<std::string>& uri_matcher,
124     const ::testing::Matcher<HttpRequest::Method>& method_matcher,
125     const ::testing::Matcher<HeaderList>& headers_matcher,
126     const ::testing::Matcher<std::string>& body_matcher);
127 
128 // A mock request callback.
129 class MockHttpRequestCallback : public HttpRequestCallback {
130  public:
131   explicit MockHttpRequestCallback() = default;
132   ~MockHttpRequestCallback() override = default;
133   MOCK_METHOD(absl::Status, OnResponseStarted,
134               (const HttpRequest& request, const HttpResponse& response),
135               (override));
136 
137   MOCK_METHOD(void, OnResponseError,
138               (const HttpRequest& request, const absl::Status& error),
139               (override));
140 
141   MOCK_METHOD(absl::Status, OnResponseBody,
142               (const HttpRequest& request, const HttpResponse& response,
143                absl::string_view data),
144               (override));
145 
146   MOCK_METHOD(void, OnResponseBodyError,
147               (const HttpRequest& request, const HttpResponse& response,
148                const absl::Status& error),
149               (override));
150 
151   MOCK_METHOD(void, OnResponseCompleted,
152               (const HttpRequest& request, const HttpResponse& response),
153               (override));
154 };
155 
156 // Creates a 'pending' `Operation`.
157 ::google::longrunning::Operation CreatePendingOperation(
158     absl::string_view operation_name);
159 
160 // Creates a 'done' `Operation`, packing the given message into an `Any`.
161 ::google::longrunning::Operation CreateDoneOperation(
162     absl::string_view operation_name, const google::protobuf::Message& inner_result);
163 
164 // Creates an `Operation` with the specified error information.
165 ::google::longrunning::Operation CreateErrorOperation(
166     absl::string_view operation_name, const absl::StatusCode error_code,
167     absl::string_view error_message);
168 
169 }  // namespace http
170 }  // namespace client
171 }  // namespace fcp
172 
173 #endif  // FCP_CLIENT_HTTP_TESTING_TEST_HELPERS_H_
174