mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Implement tests
This commit is contained in:
parent
cf23888b88
commit
6167cafbde
|
@ -20,8 +20,9 @@ set(CMAKE_CXX_STANDARD 17)
|
|||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
option(CURL_SAPI_ENABLE_EXAMPLES "" ON)
|
||||
option(CURL_SAPI_ENABLE_TESTS "" ON)
|
||||
|
||||
# Add the callbacks used by the examples
|
||||
# Add callbacks used by examples
|
||||
if (CURL_SAPI_ENABLE_EXAMPLES)
|
||||
list(APPEND CURL_SAPI_CALLBACKS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/callbacks.h"
|
||||
|
@ -29,6 +30,14 @@ if (CURL_SAPI_ENABLE_EXAMPLES)
|
|||
)
|
||||
endif()
|
||||
|
||||
# Add callbacks used by tests
|
||||
if (CURL_SAPI_ENABLE_TESTS)
|
||||
list(APPEND CURL_SAPI_CALLBACKS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/callbacks.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/callbacks.cc"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Add folder containing the non-sandboxed custom curl library
|
||||
add_subdirectory(curl_wrapper)
|
||||
|
||||
|
@ -137,3 +146,8 @@ target_include_directories(curl_sapi INTERFACE
|
|||
if (CURL_SAPI_ENABLE_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# Add tests
|
||||
if (CURL_SAPI_ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
|
|
@ -54,3 +54,10 @@ To build these examples when building the library, the cmake variable `CURL_SAPI
|
|||
|
||||
The `callbacks.h` and `callbacks.cc` files implement all the callbacks used by the examples.
|
||||
|
||||
## Policy
|
||||
|
||||
The `sandbox.h` file contains a policy allowing all is necessary for libcurl to perform simple requests. It is used by all the examples, except by example3. This example needs some additional policies and files in its namespace (since it uses HTTPS), and the file `example3.cc` shows how to easily extend an existing policy.
|
||||
|
||||
## Testing
|
||||
|
||||
The `tests` folder contains some test cases created using Google Test. The class `CurlTestUtils` is used to facilitate some tasks that all test cases need, including the setup of a mock local server on which test requests are performed.
|
||||
|
|
29
oss-internship-2020/curl/tests/CMakeLists.txt
Normal file
29
oss-internship-2020/curl/tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_subdirectory(googletest)
|
||||
include(GoogleTest)
|
||||
|
||||
add_executable(tests
|
||||
test_utils.h
|
||||
test_utils.cc
|
||||
tests.cc
|
||||
)
|
||||
|
||||
target_link_libraries(tests
|
||||
curl_sapi sapi::sapi
|
||||
gtest gmock gtest_main
|
||||
)
|
||||
|
||||
gtest_discover_tests(tests)
|
33
oss-internship-2020/curl/tests/callbacks.cc
Normal file
33
oss-internship-2020/curl/tests/callbacks.cc
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "callbacks.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
size_t write_to_memory(char* contents, size_t size, size_t nmemb, void* userp) {
|
||||
size_t realsize = size * nmemb;
|
||||
MemoryStruct* mem = (MemoryStruct*)userp;
|
||||
|
||||
char* ptr = (char*)realloc(mem->memory, mem->size + realsize + 1);
|
||||
if (ptr == NULL) return 0;
|
||||
|
||||
mem->memory = ptr;
|
||||
memcpy(&(mem->memory[mem->size]), contents, realsize);
|
||||
mem->size += realsize;
|
||||
mem->memory[mem->size] = 0;
|
||||
|
||||
return realsize;
|
||||
}
|
29
oss-internship-2020/curl/tests/callbacks.h
Normal file
29
oss-internship-2020/curl/tests/callbacks.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef TESTS_CALLBACKS_H
|
||||
#define TESTS_CALLBACKS_H
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern "C" struct MemoryStruct {
|
||||
char* memory;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// Append contents to the string stored by userp (userp is a MemoryStruct*)
|
||||
extern "C" size_t write_to_memory(char* contents, size_t size, size_t nmemb,
|
||||
void* userp);
|
||||
|
||||
#endif // TESTS_CALLBACKS_H
|
165
oss-internship-2020/curl/tests/test_utils.cc
Normal file
165
oss-internship-2020/curl/tests/test_utils.cc
Normal file
|
@ -0,0 +1,165 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
void CurlTestUtils::curl_test_set_up() {
|
||||
// Initialize sandbox2 and sapi
|
||||
sandbox = std::make_unique<CurlSapiSandbox>();
|
||||
sandbox->Init().IgnoreError();
|
||||
api = std::make_unique<CurlApi>(sandbox.get());
|
||||
|
||||
// Initialize curl
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(void* curl_raw_ptr, api->curl_easy_init());
|
||||
curl = std::make_unique<sapi::v::RemotePtr>(curl_raw_ptr);
|
||||
|
||||
// Specify request URL
|
||||
sapi::v::ConstCStr sapi_url(kUrl.c_str());
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int setopt_url_code,
|
||||
api->curl_easy_setopt_ptr(curl.get(), CURLOPT_URL, sapi_url.PtrBefore()));
|
||||
EXPECT_EQ(setopt_url_code, CURLE_OK);
|
||||
|
||||
// Set port
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int setopt_port_code,
|
||||
api->curl_easy_setopt_long(curl.get(), CURLOPT_PORT, port));
|
||||
EXPECT_EQ(setopt_port_code, CURLE_OK);
|
||||
|
||||
// Generate pointer to the write_to_memory callback
|
||||
sapi::RPCChannel rpcc(sandbox->comms());
|
||||
size_t (*_function_ptr)(char*, size_t, size_t, void*);
|
||||
EXPECT_THAT(rpcc.Symbol("write_to_memory", (void**)&_function_ptr),
|
||||
sapi::IsOk());
|
||||
sapi::v::RemotePtr remote_function_ptr((void*)_function_ptr);
|
||||
|
||||
// Set write_to_memory as the write function
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int setopt_write_function,
|
||||
api->curl_easy_setopt_ptr(curl.get(), CURLOPT_WRITEFUNCTION,
|
||||
&remote_function_ptr));
|
||||
EXPECT_EQ(setopt_write_function, CURLE_OK);
|
||||
|
||||
// Pass memory chunk object to the callback
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int setopt_write_data,
|
||||
api->curl_easy_setopt_ptr(curl.get(), CURLOPT_WRITEDATA,
|
||||
chunk.PtrBoth()));
|
||||
EXPECT_EQ(setopt_write_data, CURLE_OK);
|
||||
}
|
||||
|
||||
void CurlTestUtils::curl_test_tear_down() {
|
||||
// Cleanup curl
|
||||
api->curl_easy_cleanup(curl.get()).IgnoreError();
|
||||
}
|
||||
|
||||
void CurlTestUtils::perform_request(std::string& response) {
|
||||
// Perform the request
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int perform_code,
|
||||
api->curl_easy_perform(curl.get()));
|
||||
EXPECT_EQ(perform_code, CURLE_OK);
|
||||
|
||||
// Get pointer to the memory chunk
|
||||
sapi::v::GenericPtr remote_ptr;
|
||||
remote_ptr.SetRemote(&((MemoryStruct*)chunk.GetRemote())->memory);
|
||||
sandbox->TransferFromSandboxee(&remote_ptr).IgnoreError();
|
||||
void* chunk_ptr = (void*)remote_ptr.GetValue();
|
||||
|
||||
// Get the string and store it in response
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
response, sandbox->GetCString(sapi::v::RemotePtr(chunk_ptr)));
|
||||
}
|
||||
|
||||
void CurlTestUtils::perform_request() {
|
||||
// If the response is not needed, pass a string that will be discarded
|
||||
std::string discarded_response;
|
||||
perform_request(discarded_response);
|
||||
}
|
||||
|
||||
void CurlTestUtils::start_mock_server() {
|
||||
// Get the socket file descriptor
|
||||
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
// Create the socket address object
|
||||
// The port is set to 0, meaning that it will be auto assigned
|
||||
// Only local connections can access this socket
|
||||
sockaddr_in socket_address{AF_INET, 0, htonl(INADDR_LOOPBACK)};
|
||||
socklen_t socket_address_size = sizeof(socket_address);
|
||||
if (socket_fd == -1) return; // future.valid() is false
|
||||
|
||||
// Bind the file descriptor to the socket address object
|
||||
if (bind(socket_fd, (sockaddr*)&socket_address, socket_address_size) == -1)
|
||||
return; // future.valid() is false
|
||||
|
||||
// Assign an available port to the socket address object
|
||||
if (getsockname(socket_fd, (sockaddr*)&socket_address,
|
||||
&socket_address_size) == -1)
|
||||
return; // future.valid() is false
|
||||
|
||||
// Get the port number
|
||||
port = ntohs(socket_address.sin_port);
|
||||
|
||||
// Set server_future operation to socket listening
|
||||
server_future = std::async(std::launch::async, [=] {
|
||||
// Listen on the socket (maximum 1 connection)
|
||||
if (listen(socket_fd, 1) == -1) return false;
|
||||
|
||||
// File descriptor to the connection socket
|
||||
// This blocks the thread until a connection is established
|
||||
int accepted_socket_fd = accept(socket_fd, (sockaddr*)&socket_address,
|
||||
(socklen_t*)&socket_address_size);
|
||||
if (accepted_socket_fd == -1) return false;
|
||||
|
||||
// Read the request from the socket
|
||||
constexpr int kMaxRequestSize = 4096;
|
||||
char request[kMaxRequestSize] = {};
|
||||
if (read(accepted_socket_fd, request, kMaxRequestSize) == -1) return false;
|
||||
|
||||
// Stop any other reading operation on the socket
|
||||
if (shutdown(accepted_socket_fd, SHUT_RD) == -1) return false;
|
||||
|
||||
// Generate response depending on the HTTP method used
|
||||
std::string http_response =
|
||||
"HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: ";
|
||||
if (strncmp(request, "GET", 3) == 0) {
|
||||
http_response +=
|
||||
std::to_string(kSimpleResponse.size()) + "\n\n" + kSimpleResponse;
|
||||
} else if (strncmp(request, "POST", 4) == 0) {
|
||||
char* post_fields = strstr(request, "\r\n\r\n");
|
||||
post_fields += 4; // Points to the first char after the HTTP header
|
||||
http_response += std::to_string(strlen(post_fields)) + "\n\n" +
|
||||
std::string(post_fields);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the response on the socket
|
||||
if (write(accepted_socket_fd, http_response.c_str(),
|
||||
http_response.size()) == -1)
|
||||
return false;
|
||||
|
||||
// Close the socket
|
||||
if (close(accepted_socket_fd) == -1) return false;
|
||||
|
||||
// No error was encountered, can return true
|
||||
return true;
|
||||
});
|
||||
}
|
67
oss-internship-2020/curl/tests/test_utils.h
Normal file
67
oss-internship-2020/curl/tests/test_utils.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef TESTS_H
|
||||
#define TESTS_H
|
||||
|
||||
#include <future>
|
||||
|
||||
#include "../sandbox.h"
|
||||
#include "curl_sapi.sapi.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
|
||||
// Helper class that can be used to test Curl Sandboxed
|
||||
class CurlTestUtils {
|
||||
protected:
|
||||
struct MemoryStruct {
|
||||
char* memory;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// Initialize and set up the curl handle
|
||||
void curl_test_set_up();
|
||||
// Clean up the curl handle
|
||||
void curl_test_tear_down();
|
||||
|
||||
// Perform a request to the mock server
|
||||
// Optionally, store the response in a string
|
||||
void perform_request(std::string& response);
|
||||
void perform_request();
|
||||
|
||||
// Start a mock server that will manage connections for the tests
|
||||
// The server listens on a port asynchronously by creating a future
|
||||
// server_future.valid() is false if an error occured in the original thread
|
||||
// server_future.get() is false if an error occured in the server thread
|
||||
// The port number is stored in port
|
||||
// Responds with kSimpleResponse to a GET request
|
||||
// Responds with the POST request fields to a POST request
|
||||
void start_mock_server();
|
||||
|
||||
std::unique_ptr<CurlSapiSandbox> sandbox;
|
||||
std::unique_ptr<CurlApi> api;
|
||||
std::unique_ptr<sapi::v::RemotePtr> curl;
|
||||
|
||||
std::future<bool> server_future;
|
||||
|
||||
const std::string kUrl = "http://127.0.0.1/";
|
||||
long port;
|
||||
|
||||
const std::string kSimpleResponse = "OK";
|
||||
|
||||
sapi::v::Struct<MemoryStruct> chunk;
|
||||
};
|
||||
|
||||
#endif // TESTS_H
|
144
oss-internship-2020/curl/tests/tests.cc
Normal file
144
oss-internship-2020/curl/tests/tests.cc
Normal file
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
class Curl_Test : public CurlTestUtils, public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
// Start mock server, also sets port number
|
||||
start_mock_server();
|
||||
EXPECT_TRUE(server_future.valid());
|
||||
|
||||
curl_test_set_up();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
curl_test_tear_down();
|
||||
|
||||
// Wait for the mock server to return and check for any error
|
||||
EXPECT_TRUE(server_future.get());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(Curl_Test, EffectiveUrl) {
|
||||
sapi::v::RemotePtr effective_url_ptr(nullptr);
|
||||
|
||||
perform_request();
|
||||
|
||||
// Get effective URL
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api->curl_easy_getinfo_ptr(curl.get(), CURLINFO_EFFECTIVE_URL,
|
||||
effective_url_ptr.PtrBoth()));
|
||||
EXPECT_EQ(getinfo_code, CURLE_OK);
|
||||
|
||||
// Store effective URL in a string
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string effective_url,
|
||||
sandbox->GetCString(sapi::v::RemotePtr(
|
||||
effective_url_ptr.GetPointedVar())));
|
||||
|
||||
// Compare effective URL with original URL
|
||||
EXPECT_EQ(effective_url, kUrl);
|
||||
}
|
||||
|
||||
TEST_F(Curl_Test, EffectivePort) {
|
||||
sapi::v::Int effective_port;
|
||||
|
||||
perform_request();
|
||||
|
||||
// Get effective port
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api->curl_easy_getinfo_ptr(curl.get(), CURLINFO_PRIMARY_PORT,
|
||||
effective_port.PtrBoth()));
|
||||
EXPECT_EQ(getinfo_code, CURLE_OK);
|
||||
|
||||
// Compare effective port with port set by the mock server
|
||||
EXPECT_EQ(effective_port.GetValue(), port);
|
||||
}
|
||||
|
||||
TEST_F(Curl_Test, ResponseCode) {
|
||||
sapi::v::Int response_code;
|
||||
|
||||
perform_request();
|
||||
|
||||
// Get response code
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api->curl_easy_getinfo_ptr(curl.get(), CURLINFO_RESPONSE_CODE,
|
||||
response_code.PtrBoth()));
|
||||
EXPECT_EQ(getinfo_code, CURLE_OK);
|
||||
|
||||
// Check response code
|
||||
EXPECT_EQ(response_code.GetValue(), 200);
|
||||
}
|
||||
|
||||
TEST_F(Curl_Test, ContentType) {
|
||||
sapi::v::RemotePtr content_type_ptr(nullptr);
|
||||
|
||||
perform_request();
|
||||
|
||||
// Get effective URL
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api->curl_easy_getinfo_ptr(curl.get(), CURLINFO_CONTENT_TYPE,
|
||||
content_type_ptr.PtrBoth()));
|
||||
EXPECT_EQ(getinfo_code, CURLE_OK);
|
||||
|
||||
// Store content type in a string
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string content_type,
|
||||
sandbox->GetCString(sapi::v::RemotePtr(
|
||||
content_type_ptr.GetPointedVar())));
|
||||
|
||||
// Compare content type with "text/plain"
|
||||
EXPECT_EQ(content_type, "text/plain");
|
||||
}
|
||||
|
||||
TEST_F(Curl_Test, GETResponse) {
|
||||
std::string response;
|
||||
perform_request(response);
|
||||
|
||||
// Compare response with expected response
|
||||
EXPECT_EQ(response, kSimpleResponse);
|
||||
}
|
||||
|
||||
TEST_F(Curl_Test, POSTResponse) {
|
||||
sapi::v::ConstCStr post_fields("postfields");
|
||||
|
||||
// Set request method to POST
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int setopt_post, api->curl_easy_setopt_long(
|
||||
curl.get(), CURLOPT_POST, 1l));
|
||||
EXPECT_EQ(setopt_post, CURLE_OK);
|
||||
|
||||
// Set the size of the POST fields
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int setopt_post_fields_size,
|
||||
api->curl_easy_setopt_long(curl.get(), CURLOPT_POSTFIELDSIZE,
|
||||
post_fields.GetSize()));
|
||||
EXPECT_EQ(setopt_post_fields_size, CURLE_OK);
|
||||
|
||||
// Set the POST fields
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int setopt_post_fields,
|
||||
api->curl_easy_setopt_ptr(curl.get(), CURLOPT_POSTFIELDS,
|
||||
post_fields.PtrBefore()));
|
||||
EXPECT_EQ(setopt_post_fields, CURLE_OK);
|
||||
|
||||
std::string response;
|
||||
perform_request(response);
|
||||
|
||||
// Compare response with expected response
|
||||
EXPECT_EQ(std::string(post_fields.GetData()), response);
|
||||
}
|
Loading…
Reference in New Issue
Block a user