Merge pull request #81 from cblichmann:main

PiperOrigin-RevId: 353812058
Change-Id: I500cab1c3f44ce24e321df3a3253710911feada9
This commit is contained in:
Christian Blichmann 2021-01-26 09:40:27 +01:00
commit 2f58cfc77f
10 changed files with 160 additions and 147 deletions

View File

@ -23,7 +23,7 @@ option(SAPI_CURL_ENABLE_EXAMPLES "" ON)
option(SAPI_CURL_ENABLE_TESTS "" ON) option(SAPI_CURL_ENABLE_TESTS "" ON)
# Add callbacks used by examples and tests # 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 list(APPEND CURL_SAPI_CALLBACKS
"${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.h" "${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.h"
"${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.cc" "${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.cc"
@ -34,7 +34,7 @@ endif()
add_subdirectory(curl_wrapper) add_subdirectory(curl_wrapper)
# Setup Sandboxed API # 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_EXAMPLES ${SAPI_CURL_ENABLE_EXAMPLES} CACHE BOOL "" FORCE)
set(SAPI_ENABLE_TESTS ${SAPI_CURL_ENABLE_TESTS} CACHE BOOL "" FORCE) set(SAPI_ENABLE_TESTS ${SAPI_CURL_ENABLE_TESTS} CACHE BOOL "" FORCE)
add_subdirectory( add_subdirectory(

View File

@ -18,6 +18,7 @@
#include <cstdlib> #include <cstdlib>
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
#include "absl/strings/str_cat.h"
namespace { namespace {
@ -43,7 +44,8 @@ absl::Status Example1() {
curl_code, curl_code,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
if (curl_code != 0) { 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 // Set the library to follow a redirection
@ -51,7 +53,8 @@ absl::Status Example1() {
curl_code, curl_code,
api.curl_easy_setopt_long(&curl, curl::CURLOPT_FOLLOWLOCATION, 1l)); api.curl_easy_setopt_long(&curl, curl::CURLOPT_FOLLOWLOCATION, 1l));
if (curl_code != 0) { 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 // Disable authentication of peer certificate
@ -59,13 +62,15 @@ absl::Status Example1() {
curl_code, curl_code,
api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 0l)); api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 0l));
if (curl_code != 0) { 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 // Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) { 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 // Cleanup curl

View File

@ -19,6 +19,7 @@
#include <iostream> #include <iostream>
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
#include "absl/strings/str_cat.h"
namespace { namespace {
@ -50,7 +51,8 @@ absl::Status Example2() {
curl_code, curl_code,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
if (curl_code != 0) { 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 // Set WriteMemoryCallback as the write function
@ -58,7 +60,8 @@ absl::Status Example2() {
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEFUNCTION, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEFUNCTION,
&write_to_memory)); &write_to_memory));
if (curl_code != 0) { 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 // Pass 'chunk' struct to the callback function
@ -67,7 +70,8 @@ absl::Status Example2() {
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEDATA, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEDATA,
chunk.PtrBoth())); chunk.PtrBoth()));
if (curl_code != 0) { 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 // Set a user agent
@ -76,13 +80,15 @@ absl::Status Example2() {
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_USERAGENT, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_USERAGENT,
user_agent.PtrBefore())); user_agent.PtrBefore()));
if (curl_code != 0) { 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 // Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) { 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 // Retrieve memory size

View File

@ -65,7 +65,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
// Initialize curl (CURL_GLOBAL_DEFAULT = 3) // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (curl_code != 0) { 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 // Initialize curl easy handle
@ -82,7 +83,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
curl_code, curl_code,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
if (curl_code != 0) { 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" // 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, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERTTYPE,
ssl_cert_type.PtrBefore())); ssl_cert_type.PtrBefore()));
if (curl_code != 0) { 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 // 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, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERT,
sapi_ssl_certificate.PtrBefore())); sapi_ssl_certificate.PtrBefore()));
if (curl_code != 0) { 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 // 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, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLKEY,
sapi_ssl_key.PtrBefore())); sapi_ssl_key.PtrBefore()));
if (curl_code != 0) { 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 // 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, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_KEYPASSWD,
sapi_ssl_key_password.PtrBefore())); sapi_ssl_key_password.PtrBefore()));
if (curl_code != 0) { 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 // 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, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_CAINFO,
sapi_ca_certificates.PtrBefore())); sapi_ca_certificates.PtrBefore()));
if (curl_code != 0) { 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 // Verify the authenticity of the server
@ -135,13 +142,15 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
curl_code, curl_code,
api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 1L)); api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 1L));
if (curl_code != 0) { 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 // Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) { 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 // Cleanup curl easy handle

View File

@ -20,6 +20,7 @@
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
#include "curl_sapi.sapi.h" // NOLINT(build/include) #include "curl_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "absl/strings/str_cat.h"
namespace { namespace {
@ -37,7 +38,8 @@ absl::Status Example4() {
// Initialize curl (CURL_GLOBAL_DEFAULT = 3) // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (curl_code != 0) { 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 // Initialize http_handle
@ -54,7 +56,8 @@ absl::Status Example4() {
curl_code, api.curl_easy_setopt_ptr(&http_handle, curl::CURLOPT_URL, curl_code, api.curl_easy_setopt_ptr(&http_handle, curl::CURLOPT_URL,
url.PtrBefore())); url.PtrBefore()));
if (curl_code != 0) { 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 // Initialize multi_handle
@ -70,7 +73,8 @@ absl::Status Example4() {
SAPI_ASSIGN_OR_RETURN(curl_code, SAPI_ASSIGN_OR_RETURN(curl_code,
api.curl_multi_add_handle(&multi_handle, &http_handle)); api.curl_multi_add_handle(&multi_handle, &http_handle));
if (curl_code != 0) { 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()) { while (still_running.GetValue()) {
@ -81,7 +85,8 @@ absl::Status Example4() {
curl_code, curl_code,
api.curl_multi_perform(&multi_handle, still_running.PtrBoth())); api.curl_multi_perform(&multi_handle, still_running.PtrBoth()));
if (curl_code != 0) { 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()) { if (still_running.GetValue()) {
@ -91,8 +96,8 @@ absl::Status Example4() {
curl_code, api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000, curl_code, api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000,
numfds.PtrBoth())); numfds.PtrBoth()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError("curl_multi_poll_sapi failed: " + return absl::UnavailableError(
curl_code); absl::StrCat("curl_multi_poll_sapi failed: ", curl_code));
} }
} }
} }
@ -101,8 +106,8 @@ absl::Status Example4() {
SAPI_ASSIGN_OR_RETURN( SAPI_ASSIGN_OR_RETURN(
curl_code, api.curl_multi_remove_handle(&multi_handle, &http_handle)); curl_code, api.curl_multi_remove_handle(&multi_handle, &http_handle));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError("curl_multi_remove_handle failed: " + return absl::UnavailableError(
curl_code); absl::StrCat("curl_multi_remove_handle failed: ", curl_code));
} }
// Cleanup http_handle // Cleanup http_handle
@ -111,7 +116,8 @@ absl::Status Example4() {
// Cleanup multi_handle // Cleanup multi_handle
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_multi_cleanup(&multi_handle)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_multi_cleanup(&multi_handle));
if (curl_code != 0) { 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 // Cleanup curl

View File

@ -20,6 +20,7 @@
#include <thread> // NOLINT(build/c++11) #include <thread> // NOLINT(build/c++11)
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
#include "absl/strings/str_cat.h"
namespace { namespace {
@ -40,13 +41,15 @@ absl::Status pull_one_url(const std::string& url, curl::CurlApi& api) {
curl_code, curl_code,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, sapi_url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, sapi_url.PtrBefore()));
if (curl_code != 0) { 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 // Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) { 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 // Cleanup curl easy handle
@ -70,7 +73,8 @@ absl::Status Example5() {
// Initialize curl (CURL_GLOBAL_DEFAULT = 3) // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (curl_code != 0) { 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) // Create the threads (by using futures)

View File

@ -31,7 +31,7 @@ class CurlSapiSandbox : public curl::CurlSandbox {
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder* policy_builder) override { sandbox2::PolicyBuilder* policy_builder) override {
// Return a new policy // Return a new policy
return (*policy_builder) return sandbox2::PolicyBuilder()
.AllowDynamicStartup() .AllowDynamicStartup()
.AllowExit() .AllowExit()
.AllowFork() .AllowFork()
@ -55,13 +55,14 @@ class CurlSapiSandbox : public curl::CurlSandbox {
__NR_poll, __NR_poll,
__NR_recvfrom, __NR_recvfrom,
__NR_recvmsg, __NR_recvmsg,
__NR_rt_sigaction,
__NR_sendmmsg, __NR_sendmmsg,
__NR_sendto, __NR_sendto,
__NR_setsockopt, __NR_setsockopt,
__NR_socket, __NR_socket,
__NR_sysinfo,
}) })
.AllowUnrestrictedNetworking() .AllowUnrestrictedNetworking()
.AddDirectory("/lib")
.BuildOrDie(); .BuildOrDie();
} }
}; };

View File

@ -26,116 +26,91 @@
#include <thread> // NOLINT(build/c++11) #include <thread> // NOLINT(build/c++11)
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "sandboxed_api/util/status_macros.h"
int curl::tests::CurlTestUtils::port_; namespace curl::tests {
std::thread curl::tests::CurlTestUtils::server_thread_;
absl::Status curl::tests::CurlTestUtils::CurlTestSetUp() { int CurlTestUtils::port_;
// Initialize sandbox2 and sapi
std::thread CurlTestUtils::server_thread_;
absl::Status CurlTestUtils::CurlTestSetUp() {
// Initialize sandbox2 and SAPI
sandbox_ = std::make_unique<curl::CurlSapiSandbox>(); sandbox_ = std::make_unique<curl::CurlSapiSandbox>();
absl::Status init = sandbox_->Init(); SAPI_RETURN_IF_ERROR(sandbox_->Init());
if (!init.ok()) {
return init;
}
api_ = std::make_unique<curl::CurlApi>(sandbox_.get()); api_ = std::make_unique<curl::CurlApi>(sandbox_.get());
// Initialize curl // Initialize curl
absl::StatusOr<curl::CURL*> curl_handle = api_->curl_easy_init(); SAPI_ASSIGN_OR_RETURN(curl::CURL * curl_handle, api_->curl_easy_init());
if (!curl_handle.ok()) { if (!curl_handle) {
return curl_handle.status(); return absl::UnavailableError("curl_easy_init returned nullptr");
} }
if (!curl_handle.value()) { curl_ = std::make_unique<sapi::v::RemotePtr>(curl_handle);
return absl::UnavailableError("curl_easy_init returned NULL ");
}
curl_ = std::make_unique<sapi::v::RemotePtr>(curl_handle.value());
absl::StatusOr<int> curl_code; int curl_code = 0;
// Specify request URL // Specify request URL
sapi::v::ConstCStr sapi_url(kUrl.data()); sapi::v::ConstCStr sapi_url(kUrl);
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_URL, SAPI_ASSIGN_OR_RETURN(
sapi_url.PtrBefore()); curl_code, api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_URL,
if (!curl_code.ok()) { sapi_url.PtrBefore()));
return curl_code.status(); if (curl_code != curl::CURLE_OK) {
} return absl::UnavailableError(absl::StrCat(
if (curl_code.value() != curl::CURLE_OK) { "curl_easy_setopt_ptr returned with the error code ", curl_code));
return absl::UnavailableError(
"curl_easy_setopt_ptr returned with the error code " +
curl_code.value());
} }
// Set port // Set port
curl_code = SAPI_ASSIGN_OR_RETURN(curl_code, api_->curl_easy_setopt_long(
api_->curl_easy_setopt_long(curl_.get(), curl::CURLOPT_PORT, port_); curl_.get(), curl::CURLOPT_PORT, port_));
if (!curl_code.ok()) { if (curl_code != curl::CURLE_OK) {
return curl_code.status(); return absl::UnavailableError(absl::StrCat(
} "curl_easy_setopt_long returned with the error code ", curl_code));
if (curl_code.value() != curl::CURLE_OK) {
return absl::UnavailableError(
"curl_easy_setopt_long returned with the error code " +
curl_code.value());
} }
// Generate pointer to the WriteToMemory callback // Generate pointer to the WriteToMemory callback
void* function_ptr; void* function_ptr;
absl::Status symbol = SAPI_RETURN_IF_ERROR(
sandbox_->rpc_channel()->Symbol("WriteToMemory", &function_ptr); sandbox_->rpc_channel()->Symbol("WriteToMemory", &function_ptr));
if (!symbol.ok()) {
return symbol;
}
sapi::v::RemotePtr remote_function_ptr(function_ptr); sapi::v::RemotePtr remote_function_ptr(function_ptr);
// Set WriteToMemory as the write function // Set WriteToMemory as the write function
curl_code = api_->curl_easy_setopt_ptr( SAPI_ASSIGN_OR_RETURN(curl_code, api_->curl_easy_setopt_ptr(
curl_.get(), curl::CURLOPT_WRITEFUNCTION, &remote_function_ptr); curl_.get(), curl::CURLOPT_WRITEFUNCTION,
if (!curl_code.ok()) { &remote_function_ptr));
return curl_code.status(); if (curl_code != curl::CURLE_OK) {
} return absl::UnavailableError(absl::StrCat(
if (curl_code.value() != curl::CURLE_OK) { "curl_easy_setopt_ptr returned with the error code ", curl_code));
return absl::UnavailableError(
"curl_easy_setopt_ptr returned with the error code " +
curl_code.value());
} }
// Pass memory chunk object to the callback // Pass memory chunk object to the callback
chunk_ = std::make_unique<sapi::v::LenVal>(0); chunk_ = std::make_unique<sapi::v::LenVal>(0);
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_WRITEDATA, SAPI_ASSIGN_OR_RETURN(
chunk_->PtrBoth()); curl_code, api_->curl_easy_setopt_ptr(
if (!curl_code.ok()) { curl_.get(), curl::CURLOPT_WRITEDATA, chunk_->PtrBoth()));
return curl_code.status(); if (curl_code != curl::CURLE_OK) {
} return absl::UnavailableError(absl::StrCat(
if (curl_code.value() != curl::CURLE_OK) { "curl_easy_setopt_ptr returned with the error code ", curl_code));
return absl::UnavailableError(
"curl_easy_setopt_ptr returned with the error code " +
curl_code.value());
} }
return absl::OkStatus(); return absl::OkStatus();
} }
absl::Status curl::tests::CurlTestUtils::CurlTestTearDown() { absl::Status CurlTestUtils::CurlTestTearDown() {
// Cleanup curl // Cleanup curl
return api_->curl_easy_cleanup(curl_.get()); return api_->curl_easy_cleanup(curl_.get());
} }
absl::StatusOr<std::string> curl::tests::CurlTestUtils::PerformRequest() { absl::StatusOr<std::string> CurlTestUtils::PerformRequest() {
// Perform the request // Perform the request
absl::StatusOr<int> curl_code = api_->curl_easy_perform(curl_.get()); SAPI_ASSIGN_OR_RETURN(int curl_code, api_->curl_easy_perform(curl_.get()));
if (!curl_code.ok()) { if (curl_code != curl::CURLE_OK) {
return curl_code.status(); return absl::UnavailableError(absl::StrCat(
} "curl_easy_perform returned with the error code ", curl_code));
if (curl_code.value() != curl::CURLE_OK) {
return absl::UnavailableError(
"curl_easy_perform returned with the error code " + curl_code.value());
} }
// Get pointer to the memory chunk // Get pointer to the memory chunk
absl::Status status = sandbox_->TransferFromSandboxee(chunk_.get()); SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(chunk_.get()));
if (!status.ok()) { return std::string(reinterpret_cast<char*>(chunk_->GetData()));
return status;
}
return std::string{reinterpret_cast<char*>(chunk_->GetData())};
} }
namespace { namespace {
@ -161,8 +136,9 @@ std::string ReadUntil(const int socket, const std::string& str,
// Parse HTTP headers to return the Content-Length // Parse HTTP headers to return the Content-Length
ssize_t GetContentLength(const std::string& headers) { ssize_t GetContentLength(const std::string& headers) {
constexpr char kContentLength[] = "Content-Length: ";
// Find the Content-Length header // 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 // There is no Content-Length field
if (length_header_start == std::string::npos) { if (length_header_start == std::string::npos) {
@ -170,10 +146,8 @@ ssize_t GetContentLength(const std::string& headers) {
} }
// Find Content-Length string // Find Content-Length string
std::string::size_type length_start = const auto length_start = length_header_start + strlen(kContentLength);
length_header_start + std::string{"Content-Length: "}.size(); const auto length_bytes = headers.find("\r\n", length_start) - length_start;
std::string::size_type length_bytes =
headers.find("\r\n", length_start) - length_start;
// length_bytes exceeds maximum // length_bytes exceeds maximum
if (length_bytes >= 64) { if (length_bytes >= 64) {
@ -270,7 +244,7 @@ void ServerLoop(int listening_socket, sockaddr_in socket_address) {
} // namespace } // namespace
void curl::tests::CurlTestUtils::StartMockServer() { void CurlTestUtils::StartMockServer() {
// Get the socket file descriptor // Get the socket file descriptor
int listening_socket = socket(AF_INET, SOCK_STREAM, 0); int listening_socket = socket(AF_INET, SOCK_STREAM, 0);
@ -302,3 +276,5 @@ void curl::tests::CurlTestUtils::StartMockServer() {
// Set server_thread_ operation to socket listening // Set server_thread_ operation to socket listening
server_thread_ = std::thread(ServerLoop, listening_socket, socket_address); server_thread_ = std::thread(ServerLoop, listening_socket, socket_address);
} }
} // namespace curl::tests

View File

@ -24,33 +24,32 @@
namespace curl::tests { 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 { class CurlTestUtils {
protected: 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(); absl::Status CurlTestSetUp();
// Clean up the curl handle // Cleans up the curl handle.
absl::Status CurlTestTearDown(); 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(); absl::StatusOr<std::string> PerformRequest();
// Start a mock server (only once) that will manage connections for the tests static std::thread server_thread_;
// The server listens on a port asynchronously by creating a thread static int port_;
// 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();
std::unique_ptr<curl::CurlSapiSandbox> sandbox_; std::unique_ptr<curl::CurlSapiSandbox> sandbox_;
std::unique_ptr<curl::CurlApi> api_; std::unique_ptr<curl::CurlApi> api_;
std::unique_ptr<sapi::v::RemotePtr> curl_; 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: private:
std::unique_ptr<sapi::v::LenVal> chunk_; std::unique_ptr<sapi::v::LenVal> chunk_;
}; };

View File

@ -13,36 +13,44 @@
// limitations under the License. // limitations under the License.
#include "test_utils.h" // NOLINT(build/include) #include "test_utils.h" // NOLINT(build/include)
#include "sandboxed_api/util/status_matchers.h"
namespace curl::tests {
namespace { 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: protected:
void SetUp() override { static void SetUpTestSuite() {
// Start mock server, get port number and check for any error // Start mock server, get port number and check for any error
StartMockServer(); StartMockServer();
ASSERT_TRUE(server_thread_.joinable()); ASSERT_THAT(server_thread_.joinable(), IsTrue());
ASSERT_TRUE(CurlTestSetUp().ok());
} }
void TearDown() override { static void TearDownTestSuite() {
ASSERT_TRUE(CurlTestTearDown().ok());
// Detach the server thread // Detach the server thread
server_thread_.detach(); server_thread_.detach();
} }
void SetUp() override { ASSERT_THAT(CurlTestSetUp(), IsOk()); }
void TearDown() override { ASSERT_THAT(CurlTestTearDown(), IsOk()); }
}; };
TEST_F(CurlTest, EffectiveUrl) { TEST_F(CurlTest, EffectiveUrl) {
sapi::v::RemotePtr effective_url_ptr(nullptr); ASSERT_THAT(PerformRequest().status(), IsOk());
ASSERT_TRUE(PerformRequest().ok());
// Get effective URL // Get effective URL
sapi::v::RemotePtr effective_url_ptr(nullptr);
SAPI_ASSERT_OK_AND_ASSIGN( SAPI_ASSERT_OK_AND_ASSIGN(
int getinfo_code, int getinfo_code,
api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_EFFECTIVE_URL, api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_EFFECTIVE_URL,
effective_url_ptr.PtrBoth())); 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 // Store effective URL in a string
SAPI_ASSERT_OK_AND_ASSIGN(std::string effective_url, SAPI_ASSERT_OK_AND_ASSIGN(std::string effective_url,
@ -50,15 +58,14 @@ TEST_F(CurlTest, EffectiveUrl) {
effective_url_ptr.GetPointedVar()))); effective_url_ptr.GetPointedVar())));
// Compare effective URL with original URL // Compare effective URL with original URL
ASSERT_EQ(effective_url, kUrl); ASSERT_THAT(effective_url, Eq(kUrl));
} }
TEST_F(CurlTest, EffectivePort) { TEST_F(CurlTest, EffectivePort) {
sapi::v::Int effective_port; ASSERT_THAT(PerformRequest().status(), IsOk());
ASSERT_TRUE(PerformRequest().ok());
// Get effective port // Get effective port
sapi::v::Int effective_port;
SAPI_ASSERT_OK_AND_ASSIGN( SAPI_ASSERT_OK_AND_ASSIGN(
int getinfo_code, int getinfo_code,
api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_PRIMARY_PORT, api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_PRIMARY_PORT,
@ -70,11 +77,10 @@ TEST_F(CurlTest, EffectivePort) {
} }
TEST_F(CurlTest, ResponseCode) { TEST_F(CurlTest, ResponseCode) {
sapi::v::Int response_code; ASSERT_THAT(PerformRequest().status(), IsOk());
ASSERT_TRUE(PerformRequest().ok());
// Get response code // Get response code
sapi::v::Int response_code;
SAPI_ASSERT_OK_AND_ASSIGN( SAPI_ASSERT_OK_AND_ASSIGN(
int getinfo_code, int getinfo_code,
api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_RESPONSE_CODE, api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_RESPONSE_CODE,
@ -106,14 +112,14 @@ TEST_F(CurlTest, ContentType) {
ASSERT_EQ(content_type, "text/plain"); ASSERT_EQ(content_type, "text/plain");
} }
TEST_F(CurlTest, GETResponse) { TEST_F(CurlTest, GetResponse) {
SAPI_ASSERT_OK_AND_ASSIGN(std::string response, PerformRequest()); SAPI_ASSERT_OK_AND_ASSIGN(std::string response, PerformRequest());
// Compare response with expected response // Compare response with expected response
ASSERT_EQ(response, "OK"); ASSERT_EQ(response, "OK");
} }
TEST_F(CurlTest, POSTResponse) { TEST_F(CurlTest, PostResponse) {
sapi::v::ConstCStr post_fields("postfields"); sapi::v::ConstCStr post_fields("postfields");
// Set request method to POST // Set request method to POST
@ -143,3 +149,4 @@ TEST_F(CurlTest, POSTResponse) {
} }
} // namespace } // namespace
} // namespace curl::tests