mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Address review comments
This commit is contained in:
parent
9fed2ec097
commit
e446ec81a1
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -7,6 +7,3 @@
|
||||||
[submodule "oss-internship-2020/curl/curl_wrapper/curl"]
|
[submodule "oss-internship-2020/curl/curl_wrapper/curl"]
|
||||||
path = oss-internship-2020/curl/curl_wrapper/curl
|
path = oss-internship-2020/curl/curl_wrapper/curl
|
||||||
url = https://github.com/curl/curl
|
url = https://github.com/curl/curl
|
||||||
[submodule "oss-internship-2020/curl/tests/googletest"]
|
|
||||||
path = oss-internship-2020/curl/tests/googletest
|
|
||||||
url = git@github.com:google/googletest.git
|
|
||||||
|
|
|
@ -43,8 +43,8 @@ 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 OFF CACHE BOOL "")
|
set(SAPI_ENABLE_EXAMPLES ${CURL_SAPI_ENABLE_EXAMPLES} CACHE BOOL "" FORCE)
|
||||||
set(SAPI_ENABLE_TESTS OFF CACHE BOOL "")
|
set(SAPI_ENABLE_TESTS ${CURL_SAPI_ENABLE_TESTS} CACHE BOOL "" FORCE)
|
||||||
add_subdirectory(
|
add_subdirectory(
|
||||||
"${SAPI_ROOT}"
|
"${SAPI_ROOT}"
|
||||||
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||||
|
|
|
@ -1,7 +1,30 @@
|
||||||
# Curl Sandboxed
|
# Curl Sandbox
|
||||||
|
|
||||||
This library is a sandboxed version of curl's C API, [libcurl](https://curl.haxx.se/libcurl/c/), implemented using Sandboxed API.
|
This library is a sandboxed version of curl's C API, [libcurl](https://curl.haxx.se/libcurl/c/), implemented using Sandboxed API.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
The repository can be cloned using:
|
||||||
|
```
|
||||||
|
git clone --recursive [URL to this repo]
|
||||||
|
```
|
||||||
|
The `--recursive` flag ensures that submodules are also cloned.
|
||||||
|
|
||||||
|
Alternatively, if the repository has already been cloned but the submodules have not, these can be cloned using:
|
||||||
|
```
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
The full list of Sandboxed API dependencies can be found on [Sandboxed API Getting Started page](https://developers.google.com/sandboxed-api/docs/getting-started).
|
||||||
|
|
||||||
|
The following commands, used from the current `curl/` directory, build the library:
|
||||||
|
```
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake .. -G Ninja -D SAPI_ROOT=[path to sandboxed-api]
|
||||||
|
cmake --build .
|
||||||
|
```
|
||||||
|
|
||||||
## Implementation details
|
## Implementation details
|
||||||
|
|
||||||
All of libcurl's methods are supported by the library. However, a few of these have different signatures defined in the sandboxed header `custom_curl.h`, which wraps and extends libcurl.
|
All of libcurl's methods are supported by the library. However, a few of these have different signatures defined in the sandboxed header `custom_curl.h`, which wraps and extends libcurl.
|
||||||
|
@ -50,7 +73,7 @@ The pointers can then be obtained using an `RPCChannel` object, as shown in `exa
|
||||||
|
|
||||||
The `examples` directory contains the sandboxed versions of example source codes taken from [this page](https://curl.haxx.se/libcurl/c/example.html) on curl's website. More information about each example can be found in the examples' [README](examples/README.md).
|
The `examples` directory contains the sandboxed versions of example source codes taken from [this page](https://curl.haxx.se/libcurl/c/example.html) on curl's website. More information about each example can be found in the examples' [README](examples/README.md).
|
||||||
|
|
||||||
To build these examples when building the library, the cmake variable `CURL_SAPI_ENABLE_EXAMPLES` must be set to `ON`.
|
To build these examples when building the library, the cmake variable `CURL_SAPI_ENABLE_EXAMPLES` must be set to `ON`. This enables Sandboxed API examples as well.
|
||||||
|
|
||||||
The `callbacks.h` and `callbacks.cc` files implement all the callbacks used by the examples.
|
The `callbacks.h` and `callbacks.cc` files implement all the callbacks used by the examples.
|
||||||
|
|
||||||
|
@ -61,3 +84,5 @@ The `sandbox.h` file contains a policy allowing all is necessary for libcurl to
|
||||||
## Testing
|
## 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.
|
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.
|
||||||
|
|
||||||
|
To build these tests when building the library, the cmake variable `CURL_SAPI_ENABLE_TESTS` must be set to `ON`. This enables Sandboxed API tests as well.
|
|
@ -28,7 +28,8 @@ set_target_properties(curl_wrapper_and_callbacks
|
||||||
set(CURL_HIDDEN_SYMBOLS OFF)
|
set(CURL_HIDDEN_SYMBOLS OFF)
|
||||||
set(BUILD_SHARED_LIBS OFF)
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
|
||||||
# Link the wrapper to the original curl library
|
# Link the wrapper to the original curl library (testing is disabled in curl)
|
||||||
|
set(BUILD_TESTING OFF)
|
||||||
add_subdirectory(curl)
|
add_subdirectory(curl)
|
||||||
target_link_libraries(curl_wrapper_and_callbacks
|
target_link_libraries(curl_wrapper_and_callbacks
|
||||||
CURL::libcurl
|
CURL::libcurl
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Curl Sandboxed Examples
|
# Curl Sandbox Examples
|
||||||
|
|
||||||
Each example in this folder is the sandboxed version of a code snippet from [this page](https://curl.haxx.se/libcurl/c/example.html) on curl's website. These examples perform some basic tasks using libcurl, and can be useful both to understand how to use Curl Sandboxed, but also to get an idea of how regular and sandboxed code compare to each other.
|
Each example in this folder is the sandboxed version of a code snippet from [this page](https://curl.haxx.se/libcurl/c/example.html) on curl's website. These examples perform some basic tasks using libcurl, and can be useful both to understand how to use Curl Sandboxed, but also to get an idea of how regular and sandboxed code compare to each other.
|
||||||
|
|
||||||
|
|
|
@ -30,41 +30,49 @@ int main(int argc, char* argv[]) {
|
||||||
// Initialize sandbox2 and sapi
|
// Initialize sandbox2 and sapi
|
||||||
CurlSapiSandbox sandbox;
|
CurlSapiSandbox sandbox;
|
||||||
status = sandbox.Init();
|
status = sandbox.Init();
|
||||||
if (!status.ok())
|
if (!status.ok()) {
|
||||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||||
|
}
|
||||||
CurlApi api(&sandbox);
|
CurlApi api(&sandbox);
|
||||||
|
|
||||||
// Initialize the curl session
|
// Initialize the curl session
|
||||||
status_or_curl = api.curl_easy_init();
|
status_or_curl = api.curl_easy_init();
|
||||||
if (!status_or_curl.ok())
|
if (!status_or_curl.ok()) {
|
||||||
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
||||||
|
}
|
||||||
sapi::v::RemotePtr curl(status_or_curl.value());
|
sapi::v::RemotePtr curl(status_or_curl.value());
|
||||||
if (!curl.GetValue()) LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
if (!curl.GetValue()) LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
||||||
|
|
||||||
// Specify URL to get
|
// Specify URL to get
|
||||||
sapi::v::ConstCStr url("http://example.com");
|
sapi::v::ConstCStr url("http://example.com");
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Set the library to follow a redirection
|
// Set the library to follow a redirection
|
||||||
status_or_int = api.curl_easy_setopt_long(&curl, CURLOPT_FOLLOWLOCATION, 1l);
|
status_or_int = api.curl_easy_setopt_long(&curl, CURLOPT_FOLLOWLOCATION, 1l);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_long failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_long failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Disable authentication of peer certificate
|
// Disable authentication of peer certificate
|
||||||
status_or_int = api.curl_easy_setopt_long(&curl, CURLOPT_SSL_VERIFYPEER, 0l);
|
status_or_int = api.curl_easy_setopt_long(&curl, CURLOPT_SSL_VERIFYPEER, 0l);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_long failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_long failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the request
|
// Perform the request
|
||||||
status_or_int = api.curl_easy_perform(&curl);
|
status_or_int = api.curl_easy_perform(&curl);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_perform failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_perform failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup curl
|
// Cleanup curl
|
||||||
status = api.curl_easy_cleanup(&curl);
|
status = api.curl_easy_cleanup(&curl);
|
||||||
if (!status.ok()) LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,66 +36,80 @@ int main(int argc, char* argv[]) {
|
||||||
// Initialize sandbox2 and sapi
|
// Initialize sandbox2 and sapi
|
||||||
CurlSapiSandbox sandbox;
|
CurlSapiSandbox sandbox;
|
||||||
status = sandbox.Init();
|
status = sandbox.Init();
|
||||||
if (!status.ok())
|
if (!status.ok()) {
|
||||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||||
|
}
|
||||||
CurlApi api(&sandbox);
|
CurlApi api(&sandbox);
|
||||||
|
|
||||||
// Generate pointer to WriteMemoryCallback function
|
// Generate pointer to WriteMemoryCallback function
|
||||||
sapi::RPCChannel rpcc(sandbox.comms());
|
sapi::RPCChannel rpcc(sandbox.comms());
|
||||||
size_t (*_function_ptr)(void*, size_t, size_t, void*);
|
size_t (*_function_ptr)(void*, size_t, size_t, void*);
|
||||||
status = rpcc.Symbol("WriteMemoryCallback", (void**)&_function_ptr);
|
status = rpcc.Symbol("WriteMemoryCallback", (void**)&_function_ptr);
|
||||||
if (!status.ok()) LOG(FATAL) << "rpcc.Symbol failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "rpcc.Symbol failed: " << status;
|
||||||
|
}
|
||||||
sapi::v::RemotePtr remote_function_ptr((void*)_function_ptr);
|
sapi::v::RemotePtr remote_function_ptr((void*)_function_ptr);
|
||||||
|
|
||||||
// Initialize the curl session
|
// Initialize the curl session
|
||||||
status_or_curl = api.curl_easy_init();
|
status_or_curl = api.curl_easy_init();
|
||||||
if (!status_or_curl.ok())
|
if (!status_or_curl.ok()) {
|
||||||
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
||||||
|
}
|
||||||
sapi::v::RemotePtr curl(status_or_curl.value());
|
sapi::v::RemotePtr curl(status_or_curl.value());
|
||||||
if (!curl.GetValue()) LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
if (!curl.GetValue()) {
|
||||||
|
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
||||||
|
}
|
||||||
|
|
||||||
// Specify URL to get
|
// Specify URL to get
|
||||||
sapi::v::ConstCStr url("http://example.com");
|
sapi::v::ConstCStr url("http://example.com");
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Set WriteMemoryCallback as the write function
|
// Set WriteMemoryCallback as the write function
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_WRITEFUNCTION,
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_WRITEFUNCTION,
|
||||||
&remote_function_ptr);
|
&remote_function_ptr);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Pass 'chunk' struct to the callback function
|
// Pass 'chunk' struct to the callback function
|
||||||
sapi::v::Struct<MemoryStruct> chunk;
|
sapi::v::Struct<MemoryStruct> chunk;
|
||||||
status_or_int =
|
status_or_int =
|
||||||
api.curl_easy_setopt_ptr(&curl, CURLOPT_WRITEDATA, chunk.PtrBoth());
|
api.curl_easy_setopt_ptr(&curl, CURLOPT_WRITEDATA, chunk.PtrBoth());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Set a user agent
|
// Set a user agent
|
||||||
sapi::v::ConstCStr user_agent("libcurl-agent/1.0");
|
sapi::v::ConstCStr user_agent("libcurl-agent/1.0");
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_USERAGENT,
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_USERAGENT,
|
||||||
user_agent.PtrBefore());
|
user_agent.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the request
|
// Perform the request
|
||||||
status_or_int = api.curl_easy_perform(&curl);
|
status_or_int = api.curl_easy_perform(&curl);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_perform failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_perform failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve memory size
|
// Retrieve memory size
|
||||||
sapi::v::Int size;
|
sapi::v::Int size;
|
||||||
size.SetRemote(&((MemoryStruct*)chunk.GetRemote())->size);
|
size.SetRemote(&((MemoryStruct*)chunk.GetRemote())->size);
|
||||||
status = sandbox.TransferFromSandboxee(&size);
|
status = sandbox.TransferFromSandboxee(&size);
|
||||||
if (!status.ok())
|
if (!status.ok()) {
|
||||||
LOG(FATAL) << "sandbox.TransferFromSandboxee failed: " << status;
|
LOG(FATAL) << "sandbox.TransferFromSandboxee failed: " << status;
|
||||||
|
}
|
||||||
std::cout << "memory size: " << size.GetValue() << " bytes" << std::endl;
|
std::cout << "memory size: " << size.GetValue() << " bytes" << std::endl;
|
||||||
|
|
||||||
// Cleanup curl
|
// Cleanup curl
|
||||||
status = api.curl_easy_cleanup(&curl);
|
status = api.curl_easy_cleanup(&curl);
|
||||||
if (!status.ok()) LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,9 @@ int main(int argc, char* argv[]) {
|
||||||
sapi::StatusOr<CURL*> status_or_curl;
|
sapi::StatusOr<CURL*> status_or_curl;
|
||||||
|
|
||||||
// Get input parameters (should be absolute paths)
|
// Get input parameters (should be absolute paths)
|
||||||
if (argc != 5) LOG(FATAL) << "wrong number of arguments (4 expected)";
|
if (argc != 5) {
|
||||||
|
LOG(FATAL) << "wrong number of arguments (4 expected)";
|
||||||
|
}
|
||||||
std::string ssl_certificate = argv[1];
|
std::string ssl_certificate = argv[1];
|
||||||
std::string ssl_key = argv[2];
|
std::string ssl_key = argv[2];
|
||||||
std::string ssl_key_password = argv[3];
|
std::string ssl_key_password = argv[3];
|
||||||
|
@ -68,80 +70,97 @@ int main(int argc, char* argv[]) {
|
||||||
// Initialize sandbox2 and sapi
|
// Initialize sandbox2 and sapi
|
||||||
CurlSapiSandboxEx3 sandbox(ssl_certificate, ssl_key, ca_certificates);
|
CurlSapiSandboxEx3 sandbox(ssl_certificate, ssl_key, ca_certificates);
|
||||||
status = sandbox.Init();
|
status = sandbox.Init();
|
||||||
if (!status.ok())
|
if (!status.ok()) {
|
||||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||||
|
}
|
||||||
CurlApi api(&sandbox);
|
CurlApi api(&sandbox);
|
||||||
|
|
||||||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||||
status_or_int = api.curl_global_init(3l);
|
status_or_int = api.curl_global_init(3l);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_global_init failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_global_init failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize curl easy handle
|
// Initialize curl easy handle
|
||||||
status_or_curl = api.curl_easy_init();
|
status_or_curl = api.curl_easy_init();
|
||||||
if (!status_or_curl.ok())
|
if (!status_or_curl.ok()) {
|
||||||
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
||||||
|
}
|
||||||
sapi::v::RemotePtr curl(status_or_curl.value());
|
sapi::v::RemotePtr curl(status_or_curl.value());
|
||||||
if (!curl.GetValue()) LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
if (!curl.GetValue()) {
|
||||||
|
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
||||||
|
}
|
||||||
|
|
||||||
// Specify URL to get (using HTTPS)
|
// Specify URL to get (using HTTPS)
|
||||||
sapi::v::ConstCStr url("https://example.com");
|
sapi::v::ConstCStr url("https://example.com");
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Set the SSL certificate type to "PEM"
|
// Set the SSL certificate type to "PEM"
|
||||||
sapi::v::ConstCStr ssl_cert_type("PEM");
|
sapi::v::ConstCStr ssl_cert_type("PEM");
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLCERTTYPE,
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLCERTTYPE,
|
||||||
ssl_cert_type.PtrBefore());
|
ssl_cert_type.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Set the certificate for client authentication
|
// Set the certificate for client authentication
|
||||||
sapi::v::ConstCStr sapi_ssl_certificate(ssl_certificate.c_str());
|
sapi::v::ConstCStr sapi_ssl_certificate(ssl_certificate.c_str());
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLCERT,
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLCERT,
|
||||||
sapi_ssl_certificate.PtrBefore());
|
sapi_ssl_certificate.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Set the private key for client authentication
|
// Set the private key for client authentication
|
||||||
sapi::v::ConstCStr sapi_ssl_key(ssl_key.c_str());
|
sapi::v::ConstCStr sapi_ssl_key(ssl_key.c_str());
|
||||||
status_or_int =
|
status_or_int =
|
||||||
api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLKEY, sapi_ssl_key.PtrBefore());
|
api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLKEY, sapi_ssl_key.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Set the password used to protect the private key
|
// Set the password used to protect the private key
|
||||||
sapi::v::ConstCStr sapi_ssl_key_password(ssl_key_password.c_str());
|
sapi::v::ConstCStr sapi_ssl_key_password(ssl_key_password.c_str());
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_KEYPASSWD,
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_KEYPASSWD,
|
||||||
sapi_ssl_key_password.PtrBefore());
|
sapi_ssl_key_password.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Set the file with the certificates vaildating the server
|
// Set the file with the certificates vaildating the server
|
||||||
sapi::v::ConstCStr sapi_ca_certificates(ca_certificates.c_str());
|
sapi::v::ConstCStr sapi_ca_certificates(ca_certificates.c_str());
|
||||||
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_CAINFO,
|
status_or_int = api.curl_easy_setopt_ptr(&curl, CURLOPT_CAINFO,
|
||||||
sapi_ca_certificates.PtrBefore());
|
sapi_ca_certificates.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Verify the authenticity of the server
|
// Verify the authenticity of the server
|
||||||
status_or_int = api.curl_easy_setopt_long(&curl, CURLOPT_SSL_VERIFYPEER, 1L);
|
status_or_int = api.curl_easy_setopt_long(&curl, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_long failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_long failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the request
|
// Perform the request
|
||||||
status_or_int = api.curl_easy_perform(&curl);
|
status_or_int = api.curl_easy_perform(&curl);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_perform failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_perform failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup curl easy handle
|
// Cleanup curl easy handle
|
||||||
status = api.curl_easy_cleanup(&curl);
|
status = api.curl_easy_cleanup(&curl);
|
||||||
if (!status.ok()) LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup curl
|
// Cleanup curl
|
||||||
status = api.curl_global_cleanup();
|
status = api.curl_global_cleanup();
|
||||||
if (!status.ok()) LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,9 @@ int main(int argc, char* argv[]) {
|
||||||
// Initialize sandbox2 and sapi
|
// Initialize sandbox2 and sapi
|
||||||
CurlSapiSandbox sandbox;
|
CurlSapiSandbox sandbox;
|
||||||
status = sandbox.Init();
|
status = sandbox.Init();
|
||||||
if (!status.ok())
|
if (!status.ok()) {
|
||||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||||
|
}
|
||||||
CurlApi api(&sandbox);
|
CurlApi api(&sandbox);
|
||||||
|
|
||||||
// Number of running handles
|
// Number of running handles
|
||||||
|
@ -42,36 +43,43 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||||
status_or_int = api.curl_global_init(3l);
|
status_or_int = api.curl_global_init(3l);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_global_init failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_global_init failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize http_handle
|
// Initialize http_handle
|
||||||
status_or_curl = api.curl_easy_init();
|
status_or_curl = api.curl_easy_init();
|
||||||
if (!status_or_curl.ok())
|
if (!status_or_curl.ok()) {
|
||||||
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
||||||
|
}
|
||||||
sapi::v::RemotePtr http_handle(status_or_curl.value());
|
sapi::v::RemotePtr http_handle(status_or_curl.value());
|
||||||
if (!http_handle.GetValue())
|
if (!http_handle.GetValue()) {
|
||||||
LOG(FATAL) << "curl_easy_init failed: http_handle is NULL";
|
LOG(FATAL) << "curl_easy_init failed: http_handle is NULL";
|
||||||
|
}
|
||||||
|
|
||||||
// Specify URL to get
|
// Specify URL to get
|
||||||
sapi::v::ConstCStr url("http://example.com");
|
sapi::v::ConstCStr url("http://example.com");
|
||||||
status_or_int =
|
status_or_int =
|
||||||
api.curl_easy_setopt_ptr(&http_handle, CURLOPT_URL, url.PtrBefore());
|
api.curl_easy_setopt_ptr(&http_handle, CURLOPT_URL, url.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize multi_handle
|
// Initialize multi_handle
|
||||||
status_or_curlm = api.curl_multi_init();
|
status_or_curlm = api.curl_multi_init();
|
||||||
if (!status_or_curlm.ok())
|
if (!status_or_curlm.ok()) {
|
||||||
LOG(FATAL) << "curl_multi_init failed: " << status_or_curlm.status();
|
LOG(FATAL) << "curl_multi_init failed: " << status_or_curlm.status();
|
||||||
|
}
|
||||||
sapi::v::RemotePtr multi_handle(status_or_curlm.value());
|
sapi::v::RemotePtr multi_handle(status_or_curlm.value());
|
||||||
if (!multi_handle.GetValue())
|
if (!multi_handle.GetValue()) {
|
||||||
LOG(FATAL) << "curl_multi_init failed: multi_handle is NULL";
|
LOG(FATAL) << "curl_multi_init failed: multi_handle is NULL";
|
||||||
|
}
|
||||||
|
|
||||||
// Add http_handle to the multi stack
|
// Add http_handle to the multi stack
|
||||||
status_or_int = api.curl_multi_add_handle(&multi_handle, &http_handle);
|
status_or_int = api.curl_multi_add_handle(&multi_handle, &http_handle);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_multi_add_handle failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_multi_add_handle failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
while (still_running.GetValue()) {
|
while (still_running.GetValue()) {
|
||||||
sapi::v::Int numfds(0);
|
sapi::v::Int numfds(0);
|
||||||
|
@ -79,36 +87,44 @@ int main(int argc, char* argv[]) {
|
||||||
// Perform the request
|
// Perform the request
|
||||||
status_or_int =
|
status_or_int =
|
||||||
api.curl_multi_perform(&multi_handle, still_running.PtrBoth());
|
api.curl_multi_perform(&multi_handle, still_running.PtrBoth());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_mutli_perform failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_mutli_perform failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
if (still_running.GetValue()) {
|
if (still_running.GetValue()) {
|
||||||
// Wait for an event or timeout
|
// Wait for an event or timeout
|
||||||
sapi::v::NullPtr null_ptr;
|
sapi::v::NullPtr null_ptr;
|
||||||
status_or_int = api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0,
|
status_or_int = api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0,
|
||||||
1000, numfds.PtrBoth());
|
1000, numfds.PtrBoth());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_multi_poll_sapi failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_multi_poll_sapi failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove http_handle from the multi stack
|
// Remove http_handle from the multi stack
|
||||||
status_or_int = api.curl_multi_remove_handle(&multi_handle, &http_handle);
|
status_or_int = api.curl_multi_remove_handle(&multi_handle, &http_handle);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_multi_remove_handle failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_multi_remove_handle failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup http_handle
|
// Cleanup http_handle
|
||||||
status = api.curl_easy_cleanup(&http_handle);
|
status = api.curl_easy_cleanup(&http_handle);
|
||||||
if (!status.ok()) LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup multi_handle
|
// Cleanup multi_handle
|
||||||
status_or_int = api.curl_multi_cleanup(&multi_handle);
|
status_or_int = api.curl_multi_cleanup(&multi_handle);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_multi_cleanup failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_multi_cleanup failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup curl
|
// Cleanup curl
|
||||||
status = api.curl_global_cleanup();
|
status = api.curl_global_cleanup();
|
||||||
if (!status.ok()) LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,26 +37,33 @@ void* pull_one_url(void* args) {
|
||||||
|
|
||||||
// Initialize the curl session
|
// Initialize the curl session
|
||||||
status_or_curl = api.curl_easy_init();
|
status_or_curl = api.curl_easy_init();
|
||||||
if (!status_or_curl.ok())
|
if (!status_or_curl.ok()) {
|
||||||
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
LOG(FATAL) << "curl_easy_init failed: " << status_or_curl.status();
|
||||||
|
}
|
||||||
sapi::v::RemotePtr curl(status_or_curl.value());
|
sapi::v::RemotePtr curl(status_or_curl.value());
|
||||||
if (!curl.GetValue()) LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
if (!curl.GetValue()) {
|
||||||
|
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
||||||
|
}
|
||||||
|
|
||||||
// Specify URL to get
|
// Specify URL to get
|
||||||
sapi::v::ConstCStr sapi_url(((thread_args*)args)->url);
|
sapi::v::ConstCStr sapi_url(((thread_args*)args)->url);
|
||||||
status_or_int =
|
status_or_int =
|
||||||
api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, sapi_url.PtrBefore());
|
api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, sapi_url.PtrBefore());
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the request
|
// Perform the request
|
||||||
status_or_int = api.curl_easy_perform(&curl);
|
status_or_int = api.curl_easy_perform(&curl);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_easy_perform failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_easy_perform failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup curl
|
// Cleanup curl
|
||||||
status = api.curl_easy_cleanup(&curl);
|
status = api.curl_easy_cleanup(&curl);
|
||||||
if (!status.ok()) LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -77,33 +84,41 @@ int main(int argc, char* argv[]) {
|
||||||
// Initialize sandbox2 and sapi
|
// Initialize sandbox2 and sapi
|
||||||
CurlSapiSandbox sandbox;
|
CurlSapiSandbox sandbox;
|
||||||
status = sandbox.Init();
|
status = sandbox.Init();
|
||||||
if (!status.ok())
|
if (!status.ok()) {
|
||||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||||
|
}
|
||||||
CurlApi api(&sandbox);
|
CurlApi api(&sandbox);
|
||||||
|
|
||||||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||||
status_or_int = api.curl_global_init(3l);
|
status_or_int = api.curl_global_init(3l);
|
||||||
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK)
|
if (!status_or_int.ok() or status_or_int.value() != CURLE_OK) {
|
||||||
LOG(FATAL) << "curl_global_init failed: " << status_or_int.status();
|
LOG(FATAL) << "curl_global_init failed: " << status_or_int.status();
|
||||||
|
}
|
||||||
|
|
||||||
// Create the threads
|
// Create the threads
|
||||||
for (int i = 0; i < kThreadsnumber; ++i) {
|
for (int i = 0; i < kThreadsnumber; ++i) {
|
||||||
thread_args args = {urls[i], &api};
|
thread_args args = {urls[i], &api};
|
||||||
int error = pthread_create(&tid[i], NULL, pull_one_url, (void*)&args);
|
int error = pthread_create(&tid[i], NULL, pull_one_url, (void*)&args);
|
||||||
if (error) LOG(FATAL) << "pthread_create failed";
|
if (error) {
|
||||||
|
LOG(FATAL) << "pthread_create failed";
|
||||||
|
}
|
||||||
std::cout << "Thread " << i << " gets " << urls[i] << std::endl;
|
std::cout << "Thread " << i << " gets " << urls[i] << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join the threads
|
// Join the threads
|
||||||
for (int i = 0; i < kThreadsnumber; ++i) {
|
for (int i = 0; i < kThreadsnumber; ++i) {
|
||||||
int error = pthread_join(tid[i], NULL);
|
int error = pthread_join(tid[i], NULL);
|
||||||
if (error) LOG(FATAL) << "pthread_join failed";
|
if (error) {
|
||||||
|
LOG(FATAL) << "pthread_join failed";
|
||||||
|
}
|
||||||
std::cout << "Thread " << i << " terminated" << std::endl;
|
std::cout << "Thread " << i << " terminated" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup curl
|
// Cleanup curl
|
||||||
status = api.curl_global_cleanup();
|
status = api.curl_global_cleanup();
|
||||||
if (!status.ok()) LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
if (!status.ok()) {
|
||||||
|
LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
class CurlTransaction : public sapi::Transaction {
|
class CurlTransaction : public sapi::Transaction {
|
||||||
public:
|
public:
|
||||||
CurlTransaction(std::unique_ptr<sapi::Sandbox> sandbox)
|
explicit CurlTransaction(std::unique_ptr<sapi::Sandbox> sandbox)
|
||||||
: sapi::Transaction(std::move(sandbox)) {
|
: sapi::Transaction(std::move(sandbox)) {
|
||||||
sapi::Transaction::SetTimeLimit(kTimeOutVal);
|
sapi::Transaction::SetTimeLimit(kTimeOutVal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
add_subdirectory(googletest)
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
|
|
||||||
add_executable(tests
|
add_executable(tests
|
||||||
|
|
|
@ -17,17 +17,19 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
size_t write_to_memory(char* contents, size_t size, size_t nmemb, void* userp) {
|
size_t WriteToMemory(char* contents, size_t size, size_t num_bytes,
|
||||||
size_t realsize = size * nmemb;
|
void* userp) {
|
||||||
MemoryStruct* mem = (MemoryStruct*)userp;
|
size_t real_size = size * num_bytes;
|
||||||
|
auto* mem = static_cast<MemoryStruct*>(userp);
|
||||||
|
|
||||||
char* ptr = (char*)realloc(mem->memory, mem->size + realsize + 1);
|
char* ptr =
|
||||||
if (ptr == NULL) return 0;
|
static_cast<char*>(realloc(mem->memory, mem->size + real_size + 1));
|
||||||
|
if (ptr == nullptr) return 0;
|
||||||
|
|
||||||
mem->memory = ptr;
|
mem->memory = ptr;
|
||||||
memcpy(&(mem->memory[mem->size]), contents, realsize);
|
memcpy(&(mem->memory[mem->size]), contents, real_size);
|
||||||
mem->size += realsize;
|
mem->size += real_size;
|
||||||
mem->memory[mem->size] = 0;
|
mem->memory[mem->size] = 0;
|
||||||
|
|
||||||
return realsize;
|
return real_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ extern "C" struct MemoryStruct {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Append contents to the string stored by userp (userp is a MemoryStruct*)
|
// 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,
|
extern "C" size_t WriteToMemory(char* contents, size_t size, size_t num_bytes,
|
||||||
void* userp);
|
void* userp);
|
||||||
|
|
||||||
#endif // TESTS_CALLBACKS_H
|
#endif // TESTS_CALLBACKS_H
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit adeef192947fbc0f68fa14a6c494c8df32177508
|
|
|
@ -14,152 +14,225 @@
|
||||||
|
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
void CurlTestUtils::curl_test_set_up() {
|
long int CurlTestUtils::port_;
|
||||||
|
std::thread CurlTestUtils::server_thread_;
|
||||||
|
|
||||||
|
void CurlTestUtils::CurlTestSetUp() {
|
||||||
// Initialize sandbox2 and sapi
|
// Initialize sandbox2 and sapi
|
||||||
sandbox = std::make_unique<CurlSapiSandbox>();
|
sandbox_ = std::make_unique<CurlSapiSandbox>();
|
||||||
ASSERT_THAT(sandbox->Init(), sapi::IsOk());
|
ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
|
||||||
api = std::make_unique<CurlApi>(sandbox.get());
|
api_ = std::make_unique<CurlApi>(sandbox_.get());
|
||||||
|
|
||||||
// Initialize curl
|
// Initialize curl
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(void* curl_raw_ptr, api->curl_easy_init());
|
SAPI_ASSERT_OK_AND_ASSIGN(void* curl_raw_ptr, api_->curl_easy_init());
|
||||||
curl = std::make_unique<sapi::v::RemotePtr>(curl_raw_ptr);
|
curl_ = std::make_unique<sapi::v::RemotePtr>(curl_raw_ptr);
|
||||||
|
|
||||||
// Specify request URL
|
// Specify request URL
|
||||||
sapi::v::ConstCStr sapi_url(kUrl.c_str());
|
sapi::v::ConstCStr sapi_url(kUrl.data());
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
SAPI_ASSERT_OK_AND_ASSIGN(int setopt_url_code,
|
||||||
int setopt_url_code,
|
api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_URL,
|
||||||
api->curl_easy_setopt_ptr(curl.get(), CURLOPT_URL, sapi_url.PtrBefore()));
|
sapi_url.PtrBefore()));
|
||||||
ASSERT_EQ(setopt_url_code, CURLE_OK);
|
ASSERT_EQ(setopt_url_code, CURLE_OK);
|
||||||
|
|
||||||
// Set port
|
// Set port
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
int setopt_port_code,
|
int setopt_port_code,
|
||||||
api->curl_easy_setopt_long(curl.get(), CURLOPT_PORT, port));
|
api_->curl_easy_setopt_long(curl_.get(), CURLOPT_PORT, port_));
|
||||||
ASSERT_EQ(setopt_port_code, CURLE_OK);
|
ASSERT_EQ(setopt_port_code, CURLE_OK);
|
||||||
|
|
||||||
// Generate pointer to the write_to_memory callback
|
// Generate pointer to the WriteToMemory callback
|
||||||
sapi::RPCChannel rpcc(sandbox->comms());
|
sapi::RPCChannel rpcc(sandbox_->comms());
|
||||||
size_t (*_function_ptr)(char*, size_t, size_t, void*);
|
size_t (*_function_ptr)(char*, size_t, size_t, void*);
|
||||||
ASSERT_THAT(rpcc.Symbol("write_to_memory", (void**)&_function_ptr),
|
ASSERT_THAT(rpcc.Symbol("WriteToMemory", (void**)&_function_ptr),
|
||||||
sapi::IsOk());
|
sapi::IsOk());
|
||||||
sapi::v::RemotePtr remote_function_ptr((void*)_function_ptr);
|
sapi::v::RemotePtr remote_function_ptr((void*)_function_ptr);
|
||||||
|
|
||||||
// Set write_to_memory as the write function
|
// Set WriteToMemory as the write function
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
int setopt_write_function,
|
int setopt_write_function,
|
||||||
api->curl_easy_setopt_ptr(curl.get(), CURLOPT_WRITEFUNCTION,
|
api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_WRITEFUNCTION,
|
||||||
&remote_function_ptr));
|
&remote_function_ptr));
|
||||||
ASSERT_EQ(setopt_write_function, CURLE_OK);
|
ASSERT_EQ(setopt_write_function, CURLE_OK);
|
||||||
|
|
||||||
// Pass memory chunk object to the callback
|
// Pass memory chunk object to the callback
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
int setopt_write_data,
|
int setopt_write_data,
|
||||||
api->curl_easy_setopt_ptr(curl.get(), CURLOPT_WRITEDATA,
|
api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_WRITEDATA,
|
||||||
chunk.PtrBoth()));
|
chunk_.PtrBoth()));
|
||||||
ASSERT_EQ(setopt_write_data, CURLE_OK);
|
ASSERT_EQ(setopt_write_data, CURLE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurlTestUtils::curl_test_tear_down() {
|
void CurlTestUtils::CurlTestTearDown() {
|
||||||
// Cleanup curl
|
// Cleanup curl
|
||||||
ASSERT_THAT(api->curl_easy_cleanup(curl.get()), sapi::IsOk());
|
ASSERT_THAT(api_->curl_easy_cleanup(curl_.get()), sapi::IsOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurlTestUtils::perform_request(std::string& response) {
|
void CurlTestUtils::PerformRequest(std::string& response) {
|
||||||
// Perform the request
|
// Perform the request
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(int perform_code,
|
SAPI_ASSERT_OK_AND_ASSIGN(int perform_code,
|
||||||
api->curl_easy_perform(curl.get()));
|
api_->curl_easy_perform(curl_.get()));
|
||||||
ASSERT_EQ(perform_code, CURLE_OK);
|
ASSERT_EQ(perform_code, CURLE_OK);
|
||||||
|
|
||||||
// Get pointer to the memory chunk
|
// Get pointer to the memory chunk
|
||||||
sapi::v::GenericPtr remote_ptr;
|
sapi::v::GenericPtr remote_ptr;
|
||||||
remote_ptr.SetRemote(&((MemoryStruct*)chunk.GetRemote())->memory);
|
remote_ptr.SetRemote(&((MemoryStruct*)chunk_.GetRemote())->memory);
|
||||||
ASSERT_THAT(sandbox->TransferFromSandboxee(&remote_ptr), sapi::IsOk());
|
ASSERT_THAT(sandbox_->TransferFromSandboxee(&remote_ptr), sapi::IsOk());
|
||||||
void* chunk_ptr = (void*)remote_ptr.GetValue();
|
void* chunk_ptr = (void*)remote_ptr.GetValue();
|
||||||
|
|
||||||
// Get the string and store it in response
|
// Get the string and store it in response
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(response,
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
sandbox->GetCString(sapi::v::RemotePtr(chunk_ptr)));
|
response, sandbox_->GetCString(sapi::v::RemotePtr(chunk_ptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurlTestUtils::perform_request() {
|
void CurlTestUtils::PerformRequest() {
|
||||||
// If the response is not needed, pass a string that will be discarded
|
// If the response is not needed, pass a string that will be discarded
|
||||||
std::string discarded_response;
|
std::string discarded_response;
|
||||||
perform_request(discarded_response);
|
PerformRequest(discarded_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurlTestUtils::start_mock_server() {
|
void CurlTestUtils::StartMockServer() {
|
||||||
// Get the socket file descriptor
|
// Get ai_list, a list of addrinfo structures, the port will be set later
|
||||||
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
addrinfo hints{AI_PASSIVE, AF_INET, SOCK_STREAM};
|
||||||
|
addrinfo* ai_list;
|
||||||
|
if (getaddrinfo("127.0.0.1", NULL, &hints, &ai_list) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the socket address object
|
// Loop over ai_list, until a socket is created
|
||||||
// The port is set to 0, meaning that it will be auto assigned
|
int listening_socket;
|
||||||
// Only local connections can access this socket
|
for (addrinfo* p = ai_list;; p = p->ai_next) {
|
||||||
sockaddr_in socket_address{AF_INET, 0, htonl(INADDR_LOOPBACK)};
|
if (p == nullptr) {
|
||||||
socklen_t socket_address_size = sizeof(socket_address);
|
return;
|
||||||
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
|
// Try creating a socket
|
||||||
if (write(accepted_socket_fd, http_response.c_str(),
|
listening_socket = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||||
http_response.size()) == -1)
|
if (listening_socket >= 0) {
|
||||||
return false;
|
// Try binding the socket to the address
|
||||||
|
if (bind(listening_socket, p->ai_addr, p->ai_addrlen) >= 0) {
|
||||||
|
// Assign an arbitrary available port to the socket address object
|
||||||
|
if (getsockname(listening_socket, p->ai_addr, &p->ai_addrlen) == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
port_ = ntohs(((struct sockaddr_in*)p->ai_addr)->sin_port);
|
||||||
|
|
||||||
// Close the socket
|
break;
|
||||||
if (close(accepted_socket_fd) == -1) return false;
|
|
||||||
|
|
||||||
// No error was encountered, can return true
|
} else {
|
||||||
return true;
|
close(listening_socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(ai_list);
|
||||||
|
|
||||||
|
// Listen on the socket
|
||||||
|
if (listen(listening_socket, 256) == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set server_thread_ operation to socket listening
|
||||||
|
server_thread_ = std::thread([=] {
|
||||||
|
// Create the master fd_set containing listening_socket
|
||||||
|
fd_set master_fd_set;
|
||||||
|
FD_ZERO(&master_fd_set);
|
||||||
|
FD_SET(listening_socket, &master_fd_set);
|
||||||
|
|
||||||
|
// Create an empty fd_set, will be used for making copies of master_fd_set
|
||||||
|
fd_set copy_fd_set;
|
||||||
|
FD_ZERO(©_fd_set);
|
||||||
|
|
||||||
|
int max_fd = listening_socket;
|
||||||
|
|
||||||
|
// Keep calling select and block after a new event happens
|
||||||
|
// Doesn't stop until the process doing tests is terminated
|
||||||
|
for (;;) {
|
||||||
|
copy_fd_set = master_fd_set;
|
||||||
|
|
||||||
|
// Block and wait for a file descriptor to be ready
|
||||||
|
if (select(max_fd + 1, ©_fd_set, nullptr, nullptr, nullptr) == -1) {
|
||||||
|
close(listening_socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A file descriptor is ready, loop over all the fds to find it
|
||||||
|
for (int i = 0; i <= max_fd; ++i) {
|
||||||
|
// i is not a file desciptor in the set, skip it
|
||||||
|
if (!FD_ISSET(i, ©_fd_set)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == listening_socket) { // CASE 1: a new connection
|
||||||
|
|
||||||
|
sockaddr_storage remote_address;
|
||||||
|
socklen_t remote_address_size = sizeof(remote_address);
|
||||||
|
|
||||||
|
// Accept the connection
|
||||||
|
int accepted_socket =
|
||||||
|
accept(listening_socket, (sockaddr*)&remote_address,
|
||||||
|
&remote_address_size);
|
||||||
|
if (accepted_socket == -1) {
|
||||||
|
close(listening_socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the new socket to the fd_set and update max_fd
|
||||||
|
FD_SET(accepted_socket, &master_fd_set);
|
||||||
|
max_fd = std::max(max_fd, accepted_socket);
|
||||||
|
|
||||||
|
} else { // CASE 2: a request from an existing connection
|
||||||
|
|
||||||
|
constexpr int kMaxRequestSize = 4096;
|
||||||
|
char buf[kMaxRequestSize] = {};
|
||||||
|
|
||||||
|
// Receive message from socket
|
||||||
|
int num_bytes = recv(i, buf, sizeof(buf), 0);
|
||||||
|
if (num_bytes == -1) {
|
||||||
|
close(listening_socket);
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else if (num_bytes == 0) {
|
||||||
|
// Close the connection and remove it from fd_set
|
||||||
|
close(i);
|
||||||
|
FD_CLR(i, &master_fd_set);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Prepare a response for the request
|
||||||
|
std::string http_response =
|
||||||
|
"HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: ";
|
||||||
|
|
||||||
|
if (strncmp(buf, "GET", 3) == 0) {
|
||||||
|
http_response += std::to_string(kSimpleResponse.size()) + "\n\n" +
|
||||||
|
std::string{kSimpleResponse};
|
||||||
|
|
||||||
|
} else if (strncmp(buf, "POST", 4) == 0) {
|
||||||
|
char* post_fields = strstr(buf, "\r\n\r\n");
|
||||||
|
post_fields += 4; // Points to the first char after HTTP header
|
||||||
|
http_response += std::to_string(strlen(post_fields)) + "\n\n" +
|
||||||
|
std::string(post_fields);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
close(listening_socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the response to the request
|
||||||
|
if (write(i, http_response.c_str(), http_response.size()) == -1) {
|
||||||
|
close(listening_socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
#ifndef TESTS_H
|
#ifndef TESTS_H
|
||||||
#define TESTS_H
|
#define TESTS_H
|
||||||
|
|
||||||
#include <future>
|
|
||||||
|
|
||||||
#include "../sandbox.h"
|
#include "../sandbox.h"
|
||||||
#include "curl_sapi.sapi.h"
|
#include "curl_sapi.sapi.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
@ -32,36 +30,35 @@ class CurlTestUtils {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize and set up the curl handle
|
// Initialize and set up the curl handle
|
||||||
void curl_test_set_up();
|
void CurlTestSetUp();
|
||||||
// Clean up the curl handle
|
// Clean up the curl handle
|
||||||
void curl_test_tear_down();
|
void CurlTestTearDown();
|
||||||
|
|
||||||
// Perform a request to the mock server
|
// Perform a request to the mock server
|
||||||
// Optionally, store the response in a string
|
// Optionally, store the response in a string
|
||||||
void perform_request(std::string& response);
|
void PerformRequest(std::string& response);
|
||||||
void perform_request();
|
void PerformRequest();
|
||||||
|
|
||||||
// Start a mock server that will manage connections for the tests
|
// Start a mock server (only once) that will manage connections for the tests
|
||||||
// The server listens on a port asynchronously by creating a future
|
// The server listens on a port asynchronously by creating a thread
|
||||||
// server_future.valid() is false if an error occured in the original thread
|
// The port number is stored in port_
|
||||||
// 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 kSimpleResponse to a GET request
|
||||||
// Responds with the POST request fields to a POST request
|
// Responds with the POST request fields to a POST request
|
||||||
void start_mock_server();
|
static void StartMockServer();
|
||||||
|
|
||||||
std::unique_ptr<CurlSapiSandbox> sandbox;
|
std::unique_ptr<CurlSapiSandbox> sandbox_;
|
||||||
std::unique_ptr<CurlApi> api;
|
std::unique_ptr<CurlApi> api_;
|
||||||
std::unique_ptr<sapi::v::RemotePtr> curl;
|
std::unique_ptr<sapi::v::RemotePtr> curl_;
|
||||||
|
|
||||||
std::future<bool> server_future;
|
static std::thread server_thread_;
|
||||||
|
|
||||||
const std::string kUrl = "http://127.0.0.1/";
|
static constexpr absl::string_view kUrl = "http://127.0.0.1/";
|
||||||
long port;
|
static long port_;
|
||||||
|
|
||||||
const std::string kSimpleResponse = "OK";
|
static constexpr absl::string_view kSimpleResponse = "OK";
|
||||||
|
|
||||||
sapi::v::Struct<MemoryStruct> chunk;
|
private:
|
||||||
|
sapi::v::Struct<MemoryStruct> chunk_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TESTS_H
|
#endif // TESTS_H
|
||||||
|
|
|
@ -16,37 +16,37 @@
|
||||||
|
|
||||||
class Curl_Test : public CurlTestUtils, public ::testing::Test {
|
class Curl_Test : public CurlTestUtils, public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
static void SetUpTestSuite() {
|
||||||
// Start mock server, also sets port number
|
// Start mock server, get port number and check for any error
|
||||||
start_mock_server();
|
StartMockServer();
|
||||||
ASSERT_TRUE(server_future.valid());
|
ASSERT_TRUE(server_thread_.joinable());
|
||||||
|
|
||||||
curl_test_set_up();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override {
|
void SetUp() override { CurlTestSetUp(); }
|
||||||
curl_test_tear_down();
|
|
||||||
|
|
||||||
// Wait for the mock server to return and check for any error
|
static void TearDownTestSuite() {
|
||||||
ASSERT_TRUE(server_future.get());
|
// Detach the server thread
|
||||||
|
server_thread_.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TearDown() override { CurlTestTearDown(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(Curl_Test, EffectiveUrl) {
|
TEST_F(Curl_Test, EffectiveUrl) {
|
||||||
sapi::v::RemotePtr effective_url_ptr(nullptr);
|
sapi::v::RemotePtr effective_url_ptr(nullptr);
|
||||||
|
|
||||||
perform_request();
|
PerformRequest();
|
||||||
|
|
||||||
// Get effective URL
|
// Get effective URL
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
int getinfo_code,
|
int getinfo_code,
|
||||||
api->curl_easy_getinfo_ptr(curl.get(), CURLINFO_EFFECTIVE_URL,
|
api_->curl_easy_getinfo_ptr(curl_.get(), CURLINFO_EFFECTIVE_URL,
|
||||||
effective_url_ptr.PtrBoth()));
|
effective_url_ptr.PtrBoth()));
|
||||||
ASSERT_EQ(getinfo_code, CURLE_OK);
|
ASSERT_EQ(getinfo_code, 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,
|
||||||
sandbox->GetCString(sapi::v::RemotePtr(
|
sandbox_->GetCString(sapi::v::RemotePtr(
|
||||||
effective_url_ptr.GetPointedVar())));
|
effective_url_ptr.GetPointedVar())));
|
||||||
|
|
||||||
// Compare effective URL with original URL
|
// Compare effective URL with original URL
|
||||||
|
@ -56,29 +56,29 @@ TEST_F(Curl_Test, EffectiveUrl) {
|
||||||
TEST_F(Curl_Test, EffectivePort) {
|
TEST_F(Curl_Test, EffectivePort) {
|
||||||
sapi::v::Int effective_port;
|
sapi::v::Int effective_port;
|
||||||
|
|
||||||
perform_request();
|
PerformRequest();
|
||||||
|
|
||||||
// Get effective port
|
// Get 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(), CURLINFO_PRIMARY_PORT,
|
api_->curl_easy_getinfo_ptr(curl_.get(), CURLINFO_PRIMARY_PORT,
|
||||||
effective_port.PtrBoth()));
|
effective_port.PtrBoth()));
|
||||||
ASSERT_EQ(getinfo_code, CURLE_OK);
|
ASSERT_EQ(getinfo_code, CURLE_OK);
|
||||||
|
|
||||||
// Compare effective port with port set by the mock server
|
// Compare effective port with port set by the mock server
|
||||||
ASSERT_EQ(effective_port.GetValue(), port);
|
ASSERT_EQ(effective_port.GetValue(), port_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(Curl_Test, ResponseCode) {
|
TEST_F(Curl_Test, ResponseCode) {
|
||||||
sapi::v::Int response_code;
|
sapi::v::Int response_code;
|
||||||
|
|
||||||
perform_request();
|
PerformRequest();
|
||||||
|
|
||||||
// Get response code
|
// Get 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(), CURLINFO_RESPONSE_CODE,
|
api_->curl_easy_getinfo_ptr(curl_.get(), CURLINFO_RESPONSE_CODE,
|
||||||
response_code.PtrBoth()));
|
response_code.PtrBoth()));
|
||||||
ASSERT_EQ(getinfo_code, CURLE_OK);
|
ASSERT_EQ(getinfo_code, CURLE_OK);
|
||||||
|
|
||||||
// Check response code
|
// Check response code
|
||||||
|
@ -88,18 +88,18 @@ TEST_F(Curl_Test, ResponseCode) {
|
||||||
TEST_F(Curl_Test, ContentType) {
|
TEST_F(Curl_Test, ContentType) {
|
||||||
sapi::v::RemotePtr content_type_ptr(nullptr);
|
sapi::v::RemotePtr content_type_ptr(nullptr);
|
||||||
|
|
||||||
perform_request();
|
PerformRequest();
|
||||||
|
|
||||||
// Get effective URL
|
// Get effective URL
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
int getinfo_code,
|
int getinfo_code,
|
||||||
api->curl_easy_getinfo_ptr(curl.get(), CURLINFO_CONTENT_TYPE,
|
api_->curl_easy_getinfo_ptr(curl_.get(), CURLINFO_CONTENT_TYPE,
|
||||||
content_type_ptr.PtrBoth()));
|
content_type_ptr.PtrBoth()));
|
||||||
ASSERT_EQ(getinfo_code, CURLE_OK);
|
ASSERT_EQ(getinfo_code, CURLE_OK);
|
||||||
|
|
||||||
// Store content type in a string
|
// Store content type in a string
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string content_type,
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string content_type,
|
||||||
sandbox->GetCString(sapi::v::RemotePtr(
|
sandbox_->GetCString(sapi::v::RemotePtr(
|
||||||
content_type_ptr.GetPointedVar())));
|
content_type_ptr.GetPointedVar())));
|
||||||
|
|
||||||
// Compare content type with "text/plain"
|
// Compare content type with "text/plain"
|
||||||
|
@ -108,7 +108,7 @@ TEST_F(Curl_Test, ContentType) {
|
||||||
|
|
||||||
TEST_F(Curl_Test, GETResponse) {
|
TEST_F(Curl_Test, GETResponse) {
|
||||||
std::string response;
|
std::string response;
|
||||||
perform_request(response);
|
PerformRequest(response);
|
||||||
|
|
||||||
// Compare response with expected response
|
// Compare response with expected response
|
||||||
ASSERT_EQ(response, kSimpleResponse);
|
ASSERT_EQ(response, kSimpleResponse);
|
||||||
|
@ -118,26 +118,27 @@ TEST_F(Curl_Test, POSTResponse) {
|
||||||
sapi::v::ConstCStr post_fields("postfields");
|
sapi::v::ConstCStr post_fields("postfields");
|
||||||
|
|
||||||
// Set request method to POST
|
// Set request method to POST
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(int setopt_post, api->curl_easy_setopt_long(
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
curl.get(), CURLOPT_POST, 1l));
|
int setopt_post,
|
||||||
|
api_->curl_easy_setopt_long(curl_.get(), CURLOPT_POST, 1l));
|
||||||
ASSERT_EQ(setopt_post, CURLE_OK);
|
ASSERT_EQ(setopt_post, CURLE_OK);
|
||||||
|
|
||||||
// Set the size of the POST fields
|
// Set the size of the POST fields
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
int setopt_post_fields_size,
|
int setopt_post_fields_size,
|
||||||
api->curl_easy_setopt_long(curl.get(), CURLOPT_POSTFIELDSIZE,
|
api_->curl_easy_setopt_long(curl_.get(), CURLOPT_POSTFIELDSIZE,
|
||||||
post_fields.GetSize()));
|
post_fields.GetSize()));
|
||||||
ASSERT_EQ(setopt_post_fields_size, CURLE_OK);
|
ASSERT_EQ(setopt_post_fields_size, CURLE_OK);
|
||||||
|
|
||||||
// Set the POST fields
|
// Set the POST fields
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||||
int setopt_post_fields,
|
int setopt_post_fields,
|
||||||
api->curl_easy_setopt_ptr(curl.get(), CURLOPT_POSTFIELDS,
|
api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_POSTFIELDS,
|
||||||
post_fields.PtrBefore()));
|
post_fields.PtrBefore()));
|
||||||
ASSERT_EQ(setopt_post_fields, CURLE_OK);
|
ASSERT_EQ(setopt_post_fields, CURLE_OK);
|
||||||
|
|
||||||
std::string response;
|
std::string response;
|
||||||
perform_request(response);
|
PerformRequest(response);
|
||||||
|
|
||||||
// Compare response with expected response
|
// Compare response with expected response
|
||||||
ASSERT_EQ(std::string(post_fields.GetData()), response);
|
ASSERT_EQ(std::string(post_fields.GetData()), response);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user