mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Fix cURL example
Due to a naming mixup in `oss-internship-2020/curl/CMakeLists.txt`, the necessary `WriteToMemory()` callback was not linked into the sandboxee, leading to a segfault in the sandboxee when trying to run the tests/examples. As another issue, cURL seems to call `sysinfo` and `rt_sigaction` in recent versions and with recent libc. Drive-by changes: - Use the SAPI status macros instead of manually checking `absl::Status` - Put tests in namespace - Some Google C++-style fixes - Start the mock test server only once per test suite Fixes #72 for cURL. Signed-off-by: Christian Blichmann <cblichmann@google.com>
This commit is contained in:
parent
b98bed9860
commit
3a95d9df41
|
@ -23,7 +23,7 @@ option(SAPI_CURL_ENABLE_EXAMPLES "" ON)
|
|||
option(SAPI_CURL_ENABLE_TESTS "" ON)
|
||||
|
||||
# Add callbacks used by examples and tests
|
||||
if (CURL_SAPI_ENABLE_EXAMPLES OR CURL_SAPI_ENABLE_TESTS)
|
||||
if (SAPI_CURL_ENABLE_EXAMPLES OR SAPI_CURL_ENABLE_TESTS)
|
||||
list(APPEND CURL_SAPI_CALLBACKS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.cc"
|
||||
|
@ -34,7 +34,7 @@ endif()
|
|||
add_subdirectory(curl_wrapper)
|
||||
|
||||
# Setup Sandboxed API
|
||||
set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree")
|
||||
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
||||
set(SAPI_ENABLE_EXAMPLES ${SAPI_CURL_ENABLE_EXAMPLES} CACHE BOOL "" FORCE)
|
||||
set(SAPI_ENABLE_TESTS ${SAPI_CURL_ENABLE_TESTS} CACHE BOOL "" FORCE)
|
||||
add_subdirectory(
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <cstdlib>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -43,7 +44,8 @@ absl::Status Example1() {
|
|||
curl_code,
|
||||
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Set the library to follow a redirection
|
||||
|
@ -51,7 +53,8 @@ absl::Status Example1() {
|
|||
curl_code,
|
||||
api.curl_easy_setopt_long(&curl, curl::CURLOPT_FOLLOWLOCATION, 1l));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_long failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_long failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Disable authentication of peer certificate
|
||||
|
@ -59,13 +62,15 @@ absl::Status Example1() {
|
|||
curl_code,
|
||||
api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 0l));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_long failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_long failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_perform failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_perform failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Cleanup curl
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -50,7 +51,8 @@ absl::Status Example2() {
|
|||
curl_code,
|
||||
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Set WriteMemoryCallback as the write function
|
||||
|
@ -58,7 +60,8 @@ absl::Status Example2() {
|
|||
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEFUNCTION,
|
||||
&write_to_memory));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Pass 'chunk' struct to the callback function
|
||||
|
@ -67,7 +70,8 @@ absl::Status Example2() {
|
|||
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEDATA,
|
||||
chunk.PtrBoth()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Set a user agent
|
||||
|
@ -76,13 +80,15 @@ absl::Status Example2() {
|
|||
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_USERAGENT,
|
||||
user_agent.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_perform failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_perform failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Retrieve memory size
|
||||
|
|
|
@ -65,7 +65,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
|
|||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_global_init failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_global_init failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Initialize curl easy handle
|
||||
|
@ -82,7 +83,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
|
|||
curl_code,
|
||||
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Set the SSL certificate type to "PEM"
|
||||
|
@ -91,7 +93,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
|
|||
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERTTYPE,
|
||||
ssl_cert_type.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Set the certificate for client authentication
|
||||
|
@ -100,7 +103,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
|
|||
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERT,
|
||||
sapi_ssl_certificate.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Set the private key for client authentication
|
||||
|
@ -109,7 +113,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
|
|||
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLKEY,
|
||||
sapi_ssl_key.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Set the password used to protect the private key
|
||||
|
@ -118,7 +123,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
|
|||
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_KEYPASSWD,
|
||||
sapi_ssl_key_password.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Set the file with the certificates vaildating the server
|
||||
|
@ -127,7 +133,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
|
|||
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_CAINFO,
|
||||
sapi_ca_certificates.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Verify the authenticity of the server
|
||||
|
@ -135,13 +142,15 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
|
|||
curl_code,
|
||||
api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 1L));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_long failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_long failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_perform failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_perform failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Cleanup curl easy handle
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "curl_sapi.sapi.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
|
||||
|
@ -37,7 +38,8 @@ absl::Status Example4() {
|
|||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_global_init failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_global_init failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Initialize http_handle
|
||||
|
@ -54,7 +56,8 @@ absl::Status Example4() {
|
|||
curl_code, api.curl_easy_setopt_ptr(&http_handle, curl::CURLOPT_URL,
|
||||
url.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Initialize multi_handle
|
||||
|
@ -70,7 +73,8 @@ absl::Status Example4() {
|
|||
SAPI_ASSIGN_OR_RETURN(curl_code,
|
||||
api.curl_multi_add_handle(&multi_handle, &http_handle));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_multi_add_handle failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_multi_add_handle failed: ", curl_code));
|
||||
}
|
||||
|
||||
while (still_running.GetValue()) {
|
||||
|
@ -81,7 +85,8 @@ absl::Status Example4() {
|
|||
curl_code,
|
||||
api.curl_multi_perform(&multi_handle, still_running.PtrBoth()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_mutli_perform failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_mutli_perform failed: ", curl_code));
|
||||
}
|
||||
|
||||
if (still_running.GetValue()) {
|
||||
|
@ -91,8 +96,8 @@ absl::Status Example4() {
|
|||
curl_code, api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000,
|
||||
numfds.PtrBoth()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_multi_poll_sapi failed: " +
|
||||
curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_multi_poll_sapi failed: ", curl_code));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,8 +106,8 @@ absl::Status Example4() {
|
|||
SAPI_ASSIGN_OR_RETURN(
|
||||
curl_code, api.curl_multi_remove_handle(&multi_handle, &http_handle));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_multi_remove_handle failed: " +
|
||||
curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_multi_remove_handle failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Cleanup http_handle
|
||||
|
@ -111,7 +116,8 @@ absl::Status Example4() {
|
|||
// Cleanup multi_handle
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_multi_cleanup(&multi_handle));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_multi_cleanup failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_multi_cleanup failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Cleanup curl
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <thread> // NOLINT(build/c++11)
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -40,13 +41,15 @@ absl::Status pull_one_url(const std::string& url, curl::CurlApi& api) {
|
|||
curl_code,
|
||||
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, sapi_url.PtrBefore()));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_easy_perform failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_easy_perform failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Cleanup curl easy handle
|
||||
|
@ -70,7 +73,8 @@ absl::Status Example5() {
|
|||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
|
||||
if (curl_code != 0) {
|
||||
return absl::UnavailableError("curl_global_init failed: " + curl_code);
|
||||
return absl::UnavailableError(
|
||||
absl::StrCat("curl_global_init failed: ", curl_code));
|
||||
}
|
||||
|
||||
// Create the threads (by using futures)
|
||||
|
|
|
@ -31,7 +31,7 @@ class CurlSapiSandbox : public curl::CurlSandbox {
|
|||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder* policy_builder) override {
|
||||
// Return a new policy
|
||||
return (*policy_builder)
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFork()
|
||||
|
@ -55,13 +55,14 @@ class CurlSapiSandbox : public curl::CurlSandbox {
|
|||
__NR_poll,
|
||||
__NR_recvfrom,
|
||||
__NR_recvmsg,
|
||||
__NR_rt_sigaction,
|
||||
__NR_sendmmsg,
|
||||
__NR_sendto,
|
||||
__NR_setsockopt,
|
||||
__NR_socket,
|
||||
__NR_sysinfo,
|
||||
})
|
||||
.AllowUnrestrictedNetworking()
|
||||
.AddDirectory("/lib")
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -26,116 +26,91 @@
|
|||
#include <thread> // NOLINT(build/c++11)
|
||||
|
||||
#include "absl/status/statusor.h"
|
||||
#include "sandboxed_api/util/status_macros.h"
|
||||
|
||||
int curl::tests::CurlTestUtils::port_;
|
||||
std::thread curl::tests::CurlTestUtils::server_thread_;
|
||||
namespace curl::tests {
|
||||
|
||||
absl::Status curl::tests::CurlTestUtils::CurlTestSetUp() {
|
||||
// Initialize sandbox2 and sapi
|
||||
int CurlTestUtils::port_;
|
||||
|
||||
std::thread CurlTestUtils::server_thread_;
|
||||
|
||||
absl::Status CurlTestUtils::CurlTestSetUp() {
|
||||
// Initialize sandbox2 and SAPI
|
||||
sandbox_ = std::make_unique<curl::CurlSapiSandbox>();
|
||||
absl::Status init = sandbox_->Init();
|
||||
if (!init.ok()) {
|
||||
return init;
|
||||
}
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->Init());
|
||||
api_ = std::make_unique<curl::CurlApi>(sandbox_.get());
|
||||
|
||||
// Initialize curl
|
||||
absl::StatusOr<curl::CURL*> curl_handle = api_->curl_easy_init();
|
||||
if (!curl_handle.ok()) {
|
||||
return curl_handle.status();
|
||||
SAPI_ASSIGN_OR_RETURN(curl::CURL* curl_handle, api_->curl_easy_init());
|
||||
if (!curl_handle) {
|
||||
return absl::UnavailableError("curl_easy_init returned nullptr");
|
||||
}
|
||||
if (!curl_handle.value()) {
|
||||
return absl::UnavailableError("curl_easy_init returned NULL ");
|
||||
}
|
||||
curl_ = std::make_unique<sapi::v::RemotePtr>(curl_handle.value());
|
||||
curl_ = std::make_unique<sapi::v::RemotePtr>(curl_handle);
|
||||
|
||||
absl::StatusOr<int> curl_code;
|
||||
int curl_code = 0;
|
||||
|
||||
// Specify request URL
|
||||
sapi::v::ConstCStr sapi_url(kUrl.data());
|
||||
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_URL,
|
||||
sapi_url.PtrBefore());
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_setopt_ptr returned with the error code " +
|
||||
curl_code.value());
|
||||
sapi::v::ConstCStr sapi_url(kUrl);
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
curl_code, api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_URL,
|
||||
sapi_url.PtrBefore()));
|
||||
if (curl_code != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(absl::StrCat(
|
||||
"curl_easy_setopt_ptr returned with the error code ", curl_code));
|
||||
}
|
||||
|
||||
// Set port
|
||||
curl_code =
|
||||
api_->curl_easy_setopt_long(curl_.get(), curl::CURLOPT_PORT, port_);
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_setopt_long returned with the error code " +
|
||||
curl_code.value());
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api_->curl_easy_setopt_long(
|
||||
curl_.get(), curl::CURLOPT_PORT, port_));
|
||||
if (curl_code != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(absl::StrCat(
|
||||
"curl_easy_setopt_long returned with the error code ", curl_code));
|
||||
}
|
||||
|
||||
// Generate pointer to the WriteToMemory callback
|
||||
void* function_ptr;
|
||||
absl::Status symbol =
|
||||
sandbox_->rpc_channel()->Symbol("WriteToMemory", &function_ptr);
|
||||
if (!symbol.ok()) {
|
||||
return symbol;
|
||||
}
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
sandbox_->rpc_channel()->Symbol("WriteToMemory", &function_ptr));
|
||||
sapi::v::RemotePtr remote_function_ptr(function_ptr);
|
||||
|
||||
// Set WriteToMemory as the write function
|
||||
curl_code = api_->curl_easy_setopt_ptr(
|
||||
curl_.get(), curl::CURLOPT_WRITEFUNCTION, &remote_function_ptr);
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_setopt_ptr returned with the error code " +
|
||||
curl_code.value());
|
||||
SAPI_ASSIGN_OR_RETURN(curl_code, api_->curl_easy_setopt_ptr(
|
||||
curl_.get(), curl::CURLOPT_WRITEFUNCTION,
|
||||
&remote_function_ptr));
|
||||
if (curl_code != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(absl::StrCat(
|
||||
"curl_easy_setopt_ptr returned with the error code ", curl_code));
|
||||
}
|
||||
|
||||
// Pass memory chunk object to the callback
|
||||
chunk_ = std::make_unique<sapi::v::LenVal>(0);
|
||||
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_WRITEDATA,
|
||||
chunk_->PtrBoth());
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_setopt_ptr returned with the error code " +
|
||||
curl_code.value());
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
curl_code, api_->curl_easy_setopt_ptr(
|
||||
curl_.get(), curl::CURLOPT_WRITEDATA, chunk_->PtrBoth()));
|
||||
if (curl_code != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(absl::StrCat(
|
||||
"curl_easy_setopt_ptr returned with the error code ", curl_code));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status curl::tests::CurlTestUtils::CurlTestTearDown() {
|
||||
absl::Status CurlTestUtils::CurlTestTearDown() {
|
||||
// Cleanup curl
|
||||
return api_->curl_easy_cleanup(curl_.get());
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> curl::tests::CurlTestUtils::PerformRequest() {
|
||||
absl::StatusOr<std::string> CurlTestUtils::PerformRequest() {
|
||||
// Perform the request
|
||||
absl::StatusOr<int> curl_code = api_->curl_easy_perform(curl_.get());
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_perform returned with the error code " + curl_code.value());
|
||||
SAPI_ASSIGN_OR_RETURN(int curl_code, api_->curl_easy_perform(curl_.get()));
|
||||
if (curl_code != curl::CURLE_OK) {
|
||||
return absl::UnavailableError(absl::StrCat(
|
||||
"curl_easy_perform returned with the error code ", curl_code));
|
||||
}
|
||||
|
||||
// Get pointer to the memory chunk
|
||||
absl::Status status = sandbox_->TransferFromSandboxee(chunk_.get());
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return std::string{reinterpret_cast<char*>(chunk_->GetData())};
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(chunk_.get()));
|
||||
return std::string(reinterpret_cast<char*>(chunk_->GetData()));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -161,8 +136,9 @@ std::string ReadUntil(const int socket, const std::string& str,
|
|||
|
||||
// Parse HTTP headers to return the Content-Length
|
||||
ssize_t GetContentLength(const std::string& headers) {
|
||||
constexpr char kContentLength[] = "Content-Length: ";
|
||||
// Find the Content-Length header
|
||||
std::string::size_type length_header_start = headers.find("Content-Length: ");
|
||||
const auto length_header_start = headers.find(kContentLength);
|
||||
|
||||
// There is no Content-Length field
|
||||
if (length_header_start == std::string::npos) {
|
||||
|
@ -170,9 +146,8 @@ ssize_t GetContentLength(const std::string& headers) {
|
|||
}
|
||||
|
||||
// Find Content-Length string
|
||||
std::string::size_type length_start =
|
||||
length_header_start + std::string{"Content-Length: "}.size();
|
||||
std::string::size_type length_bytes =
|
||||
const auto length_start = length_header_start + strlen(kContentLength);
|
||||
const auto length_bytes =
|
||||
headers.find("\r\n", length_start) - length_start;
|
||||
|
||||
// length_bytes exceeds maximum
|
||||
|
@ -270,7 +245,7 @@ void ServerLoop(int listening_socket, sockaddr_in socket_address) {
|
|||
|
||||
} // namespace
|
||||
|
||||
void curl::tests::CurlTestUtils::StartMockServer() {
|
||||
void CurlTestUtils::StartMockServer() {
|
||||
// Get the socket file descriptor
|
||||
int listening_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
|
@ -302,3 +277,5 @@ void curl::tests::CurlTestUtils::StartMockServer() {
|
|||
// Set server_thread_ operation to socket listening
|
||||
server_thread_ = std::thread(ServerLoop, listening_socket, socket_address);
|
||||
}
|
||||
|
||||
} // namespace curl::tests
|
||||
|
|
|
@ -24,33 +24,32 @@
|
|||
|
||||
namespace curl::tests {
|
||||
|
||||
// Helper class that can be used to test Curl Sandboxed
|
||||
// Helper class that can be used to test Curl sandbox.
|
||||
class CurlTestUtils {
|
||||
protected:
|
||||
// Initialize and set up the curl handle
|
||||
static constexpr char kUrl[] = "http://127.0.0.1/";
|
||||
|
||||
// Starts a mock server (only once) that will manage connections for the
|
||||
// tests. The server listens on a port asynchronously by creating a thread.
|
||||
// The port number is stored in port_. Responds with "OK" to a GET request,
|
||||
// responds with the POST request fields to a POST request.
|
||||
static void StartMockServer();
|
||||
|
||||
// Initializes and sets up the curl handle.
|
||||
absl::Status CurlTestSetUp();
|
||||
// Clean up the curl handle
|
||||
// Cleans up the curl handle.
|
||||
absl::Status CurlTestTearDown();
|
||||
|
||||
// Perform a request to the mock server, return the response
|
||||
// Performs a request to the mock server, returning the response.
|
||||
absl::StatusOr<std::string> PerformRequest();
|
||||
|
||||
// Start a mock server (only once) that will manage connections for the tests
|
||||
// The server listens on a port asynchronously by creating a thread
|
||||
// The port number is stored in port_
|
||||
// Responds with "OK" to a GET request
|
||||
// Responds with the POST request fields to a POST request
|
||||
static void StartMockServer();
|
||||
static std::thread server_thread_;
|
||||
static int port_;
|
||||
|
||||
std::unique_ptr<curl::CurlSapiSandbox> sandbox_;
|
||||
std::unique_ptr<curl::CurlApi> api_;
|
||||
std::unique_ptr<sapi::v::RemotePtr> curl_;
|
||||
|
||||
static std::thread server_thread_;
|
||||
|
||||
static constexpr absl::string_view kUrl = "http://127.0.0.1/";
|
||||
static int port_;
|
||||
|
||||
private:
|
||||
std::unique_ptr<sapi::v::LenVal> chunk_;
|
||||
};
|
||||
|
|
|
@ -13,36 +13,48 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include "test_utils.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
|
||||
namespace curl::tests {
|
||||
namespace {
|
||||
|
||||
class CurlTest : public curl::tests::CurlTestUtils, public ::testing::Test {
|
||||
using ::sapi::IsOk;
|
||||
using ::sapi::StatusIs;
|
||||
using ::testing::Eq;
|
||||
using ::testing::IsTrue;
|
||||
|
||||
class CurlTest : public CurlTestUtils, public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
static void SetUpTestSuite() {
|
||||
// Start mock server, get port number and check for any error
|
||||
StartMockServer();
|
||||
ASSERT_TRUE(server_thread_.joinable());
|
||||
ASSERT_TRUE(CurlTestSetUp().ok());
|
||||
ASSERT_THAT(server_thread_.joinable(), IsTrue());
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
// Detach the server thread
|
||||
server_thread_.detach();
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
ASSERT_THAT(CurlTestSetUp(), IsOk());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
ASSERT_TRUE(CurlTestTearDown().ok());
|
||||
// Detach the server thread
|
||||
server_thread_.detach();
|
||||
ASSERT_THAT(CurlTestTearDown(), IsOk());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CurlTest, EffectiveUrl) {
|
||||
sapi::v::RemotePtr effective_url_ptr(nullptr);
|
||||
|
||||
ASSERT_TRUE(PerformRequest().ok());
|
||||
ASSERT_THAT(PerformRequest().status(), IsOk());
|
||||
|
||||
// Get effective URL
|
||||
sapi::v::RemotePtr effective_url_ptr(nullptr);
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_EFFECTIVE_URL,
|
||||
effective_url_ptr.PtrBoth()));
|
||||
ASSERT_EQ(getinfo_code, curl::CURLE_OK);
|
||||
ASSERT_THAT(getinfo_code, Eq(curl::CURLE_OK));
|
||||
|
||||
// Store effective URL in a string
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string effective_url,
|
||||
|
@ -50,15 +62,14 @@ TEST_F(CurlTest, EffectiveUrl) {
|
|||
effective_url_ptr.GetPointedVar())));
|
||||
|
||||
// Compare effective URL with original URL
|
||||
ASSERT_EQ(effective_url, kUrl);
|
||||
ASSERT_THAT(effective_url, Eq(kUrl));
|
||||
}
|
||||
|
||||
TEST_F(CurlTest, EffectivePort) {
|
||||
sapi::v::Int effective_port;
|
||||
|
||||
ASSERT_TRUE(PerformRequest().ok());
|
||||
ASSERT_THAT(PerformRequest().status(), IsOk());
|
||||
|
||||
// Get effective port
|
||||
sapi::v::Int effective_port;
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_PRIMARY_PORT,
|
||||
|
@ -70,11 +81,10 @@ TEST_F(CurlTest, EffectivePort) {
|
|||
}
|
||||
|
||||
TEST_F(CurlTest, ResponseCode) {
|
||||
sapi::v::Int response_code;
|
||||
|
||||
ASSERT_TRUE(PerformRequest().ok());
|
||||
ASSERT_THAT(PerformRequest().status(), IsOk());
|
||||
|
||||
// Get response code
|
||||
sapi::v::Int response_code;
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_RESPONSE_CODE,
|
||||
|
@ -106,14 +116,14 @@ TEST_F(CurlTest, ContentType) {
|
|||
ASSERT_EQ(content_type, "text/plain");
|
||||
}
|
||||
|
||||
TEST_F(CurlTest, GETResponse) {
|
||||
TEST_F(CurlTest, GetResponse) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string response, PerformRequest());
|
||||
|
||||
// Compare response with expected response
|
||||
ASSERT_EQ(response, "OK");
|
||||
}
|
||||
|
||||
TEST_F(CurlTest, POSTResponse) {
|
||||
TEST_F(CurlTest, PostResponse) {
|
||||
sapi::v::ConstCStr post_fields("postfields");
|
||||
|
||||
// Set request method to POST
|
||||
|
@ -143,3 +153,4 @@ TEST_F(CurlTest, POSTResponse) {
|
|||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace curl::tests
|
||||
|
|
Loading…
Reference in New Issue
Block a user