Address review comments

This commit is contained in:
Federico Stazi 2020-09-25 15:06:24 +00:00
parent 192e443b7c
commit a61421621c
14 changed files with 333 additions and 293 deletions

View File

@ -1,4 +1,3 @@
# Copyright 2020 Google LLC # Copyright 2020 Google LLC
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
@ -13,13 +12,20 @@
# 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.
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.12)
project(libuv_sandbox) project(libuv_sandbox)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
# Add SAPI directories
add_subdirectory(
"${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
EXCLUDE_FROM_ALL
)
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/uv_wrapper") file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/uv_wrapper")
add_custom_command( add_custom_command(
@ -28,33 +34,33 @@ add_custom_command(
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND python3 "generator/wrapper_generator.py" COMMAND "${SAPI_PYTHON3_EXECUTABLE}"
"libuv/include/uv.h" "generator/wrapper_generator.py"
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.h" "libuv/include/uv.h"
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.cc" "${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.h"
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.cc"
COMMENT "Generate the wrapper header and source files" COMMENT "Generate the wrapper header and source files"
) )
option(UV_SAPI_ENABLE_EXAMPLES "" ON) option(SAPI_UV_ENABLE_EXAMPLES "" ON)
option(UV_SAPI_ENABLE_TESTS "" ON) option(SAPI_UV_ENABLE_TESTS "" ON)
# Add callbacks used by examples and tests # Add callbacks used by examples and tests
if (UV_SAPI_ENABLE_EXAMPLES OR UV_SAPI_ENABLE_TESTS) if (SAPI_UV_ENABLE_EXAMPLES OR SAPI_UV_ENABLE_TESTS)
list(APPEND UV_SAPI_CALLBACKS list(APPEND SAPI_UV_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"
) )
endif() endif()
# Wrapper library including wrappers for all libuv methods and callbacks # Wrapper library including wrappers for all libuv methods and callbacks
# The UV_SAPI_CALLBACKS variable should contain the absolute paths of # The SAPI_UV_CALLBACKS variable should contain the absolute paths of
# all the files implementing the callbacks # all the files implementing the callbacks
add_library(uv_wrapper_and_callbacks OBJECT add_library(uv_wrapper_and_callbacks OBJECT
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.h" "${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.h"
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.cc" "${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.cc"
"${UV_SAPI_CALLBACKS}" "${SAPI_UV_CALLBACKS}"
) )
set_target_properties(uv_wrapper_and_callbacks set_target_properties(uv_wrapper_and_callbacks
PROPERTIES LINKER_LANGUAGE C PROPERTIES LINKER_LANGUAGE C
@ -66,13 +72,8 @@ target_link_libraries(uv_wrapper_and_callbacks uv_a)
# 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 ${UV_SAPI_ENABLE_EXAMPLES} CACHE BOOL "" FORCE) set(SAPI_ENABLE_EXAMPLES ${SAPI_UV_ENABLE_EXAMPLES} CACHE BOOL "" FORCE)
set(SAPI_ENABLE_TESTS ${UV_SAPI_ENABLE_TESTS} CACHE BOOL "" FORCE) set(SAPI_ENABLE_TESTS ${SAPI_UV_ENABLE_TESTS} CACHE BOOL "" FORCE)
add_subdirectory(
"${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
EXCLUDE_FROM_ALL
)
# Generate SAPI header # Generate SAPI header
add_sapi_library(uv_sapi add_sapi_library(uv_sapi
@ -374,8 +375,7 @@ add_sapi_library(uv_sapi
LIBRARY_NAME UV LIBRARY_NAME UV
NAMESPACE "" NAMESPACE uv
) )
# Include generated SAPI header # Include generated SAPI header
@ -384,11 +384,11 @@ target_include_directories(uv_sapi INTERFACE
) )
# Add examples # Add examples
if (UV_SAPI_ENABLE_EXAMPLES) if (SAPI_UV_ENABLE_EXAMPLES)
add_subdirectory(examples) add_subdirectory(examples)
endif() endif()
# Add tests # Add tests
if (UV_SAPI_ENABLE_TESTS) if (SAPI_UV_ENABLE_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()

View File

@ -1,6 +1,7 @@
# LibUV Sandbox # LibUV Sandbox
This library is a sandboxed version of [LibUV](https://libuv.org/), implemented using Sandboxed API. This library is a sandboxed version of [LibUV](https://libuv.org/), implemented
using Sandboxed API.
## Setup ## Setup
@ -8,16 +9,19 @@ The repository can be cloned using:
``` ```
git clone --recursive [URL to this repo] git clone --recursive [URL to this repo]
``` ```
The `--recursive` flag ensures that submodules are also cloned. 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: Alternatively, if the repository has already been cloned but the submodules have
not, these can be cloned using:
``` ```
git submodule update --init --recursive 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 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 `libuv/` directory, build the library: The following commands, used from the current `libuv/` directory, build the
library:
``` ```
mkdir -p build mkdir -p build
cd build cd build
@ -27,36 +31,63 @@ cmake --build .
## Implementation details ## Implementation details
LibUV can't be directly sandboxed by Sandboxed API. Because of the size and complexity of the library, doing so creates some compilation errors and does not create the correct APIs for all methods. The solution for this issue is creating a wrapper library, whose methods (which can be sandboxed properly) internally call the original LibUV's methods. LibUV can't be directly sandboxed by Sandboxed API. Because of the size and
complexity of the library, doing so creates some compilation errors and does not
create the correct APIs for all methods. The solution for this issue is creating
a wrapper library, whose methods (which can be sandboxed properly) internally
call the original LibUV's methods.
Using these wrapper methods is extremely simple, the only relevant difference is that they have a `sapi_` prefix before their names (e.g. `uv_loop_init` becomes `sapi_uv_loop_init`). The only exception is the variadic method `uv_loop_configure`. This has two wrappers, `sapi_uv_loop_configure` (with no additional parameters) and `sapi_uv_loop_configure_int` (with an additional `int` parameter). Currently, these are the only valid calls to the method in LibUV. Using these wrapper methods is extremely simple, the only relevant difference is
that they have a `sapi_` prefix before their names (e.g. `uv_loop_init` becomes
`sapi_uv_loop_init`). The only exception is the variadic method
`uv_loop_configure`. This has two wrappers, `sapi_uv_loop_configure` (with no
additional parameters) and `sapi_uv_loop_configure_int` (with an additional
`int` parameter). Currently, these are the only valid calls to the method in
LibUV.
#### Wrapper generator #### Wrapper generator
The wrapper is generated automatically by a Python script that is called by CMake at build time. This script can be found in the `generator` folder. The wrapper is generated automatically by a Python script that is called by
CMake at build time. This script can be found in the `generator` folder.
#### Function pointers #### Function pointers
The functions whose pointers will be passed to the library's methods (*callbacks*) can't be implemented in the files making use of the library, but must be in other files. These files must be compiled together with the library, and this is done by adding their absolute path to the CMake variable `UV_SAPI_CALLBACKS`. The functions whose pointers will be passed to the library's methods
(*callbacks*) can't be implemented in the files making use of the library, but
must be in other files. These files must be compiled together with the library,
and this is done by adding their absolute path to the CMake variable
`SAPI_UV_CALLBACKS`.
The pointers can then be obtained using an `RPCChannel` object, as shown in the example `idle-basic.cc`. The pointers can then be obtained using an `RPCChannel` object, as shown in the
example `idle-basic.cc`.
## Examples ## Examples
The `examples` directory contains the sandboxed versions of example source codes taken from from [LibUV's User Guide](https://docs.libuv.org/en/v1.x/guide.html). 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 from [LibUV's User Guide](https://docs.libuv.org/en/v1.x/guide.html).
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 `UV_SAPI_ENABLE_EXAMPLES` must be set to `ON`. This enables Sandboxed API examples as well. To build these examples when building the library, the CMake variable
`SAPI_UV_ENABLE_EXAMPLES` must be set to `ON`. This enables Sandboxed API
examples as well.
## Testing ## Testing
The `tests` folder contains some test cases created using Google Test. The `tests` folder contains some test cases created using Google Test.
To build these tests when building the library, the CMake variable `UV_SAPI_ENABLE_TESTS` must be set to `ON`. This enables Sandboxed API tests as well. To build these tests when building the library, the CMake variable
`SAPI_UV_ENABLE_TESTS` must be set to `ON`. This enables Sandboxed API tests as
well.
## Policies ## Policies
Each example and test has an ad-hoc policy implemented on its own file. These policies can be used as references for pieces of code that perform similar operations. For example, the `helloworld.cc` example has a policy that only allows the strictly necessary syscalls for running a loop. Each example and test has an ad-hoc policy implemented on its own file. These
policies can be used as references for pieces of code that perform similar
operations. For example, the `helloworld.cc` example has a policy that only
allows the strictly necessary syscalls for running a loop.
## Callbacks ## Callbacks
The `callbacks.h` and `callbacks.cc` files in the `callbacks` folder implement all the callbacks used by examples and tests. The `callbacks.h` and `callbacks.cc` files in the `callbacks` folder implement
all the callbacks used by examples and tests.

View File

@ -12,38 +12,36 @@
// 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.
#include "callbacks.h" #include "callbacks.h" // NOLINT(build/include)
#include <iostream> #include <iostream>
size_t iterations = 0; size_t g_iterations = 0;
size_t constexpr kMaxIterations = 1'000'000; size_t constexpr kMaxIterations = 1'000'000;
static char g_buffer[1024];
static uv_buf_t g_iov;
// Stop the handle if the methods was called kMaxIterations times // Stop the handle if the methods was called kMaxIterations times
void IdleCallback(uv_idle_t* handle) { void IdleCallback(uv_idle_t* handle) {
iterations++; ++g_iterations;
if (iterations > kMaxIterations) { if (g_iterations > kMaxIterations) {
std::cout << "IdleCallback was called " << kMaxIterations << " times" std::cout << "IdleCallback was called " << kMaxIterations << " times"
<< std::endl; << std::endl;
uv_idle_stop(handle); uv_idle_stop(handle);
} }
} }
static char buffer[1024];
static uv_buf_t iov;
// Called after some chars have been written // Called after some chars have been written
// As soon as writing of these bytes is completed, read more // As soon as writing of these bytes is completed, read more
void OnWrite(uv_fs_t* req) { void OnWrite(uv_fs_t* req) {
if (req->result < 0) { if (req->result < 0) {
std::cerr << "Write error: " << uv_strerror(static_cast<int>(req->result)) std::cerr << "Write error: " << uv_strerror(static_cast<int>(req->result))
<< std::endl; << std::endl;
return;
} else {
// Start reading more after writing these bytes
uv_fs_read(uv_default_loop(), &read_req, open_req.result, &iov, 1, -1,
OnRead);
} }
// Start reading more after writing these bytes
uv_fs_read(uv_default_loop(), &read_req, open_req.result, &g_iov, 1, -1,
OnRead);
} }
// Called after some chars have been read // Called after some chars have been read
@ -51,16 +49,16 @@ void OnWrite(uv_fs_t* req) {
void OnRead(uv_fs_t* req) { void OnRead(uv_fs_t* req) {
if (req->result < 0) { if (req->result < 0) {
std::cerr << "Read error: " << uv_strerror(req->result) << std::endl; std::cerr << "Read error: " << uv_strerror(req->result) << std::endl;
return;
} else if (req->result == 0) { }
if (req->result == 0) {
// No more bytes left, close the loop // No more bytes left, close the loop
uv_fs_t close_req; uv_fs_t close_req;
uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL); uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
} else if (req->result > 0) { } else if (req->result > 0) {
// Start writing after reading some bytes // Start writing after reading some bytes
iov.len = req->result; g_iov.len = req->result;
uv_fs_write(uv_default_loop(), &write_req, 1, &iov, 1, -1, OnWrite); uv_fs_write(uv_default_loop(), &write_req, 1, &g_iov, 1, -1, OnWrite);
} }
} }
@ -69,18 +67,17 @@ void OnRead(uv_fs_t* req) {
void OnOpen(uv_fs_t* req) { void OnOpen(uv_fs_t* req) {
if (req != &open_req) { if (req != &open_req) {
std::cerr << "Open error: req != &open_req" << std::endl; std::cerr << "Open error: req != &open_req" << std::endl;
return;
} else if (req->result < 0) { }
if (req->result < 0) {
std::cerr << "Open error: " << uv_strerror(static_cast<int>(req->result)) std::cerr << "Open error: " << uv_strerror(static_cast<int>(req->result))
<< std::endl; << std::endl;
return;
} else {
// Initialize uv_buf_t buffer
iov = uv_buf_init(buffer, sizeof(buffer));
// Start reading after opening
uv_fs_read(uv_default_loop(), &read_req, req->result, &iov, 1, -1, OnRead);
} }
// Initialize uv_buf_t g_buffer
g_iov = uv_buf_init(g_buffer, sizeof(g_buffer));
// Start reading after opening
uv_fs_read(uv_default_loop(), &read_req, req->result, &g_iov, 1, -1, OnRead);
} }
// Get the integer pointed by handle->data and increment it by one // Get the integer pointed by handle->data and increment it by one
@ -88,6 +85,6 @@ void OnOpen(uv_fs_t* req) {
void TimerCallback(uv_timer_t* handle) { void TimerCallback(uv_timer_t* handle) {
int* data = static_cast<int*>( int* data = static_cast<int*>(
uv_handle_get_data(reinterpret_cast<uv_handle_t*>(handle))); uv_handle_get_data(reinterpret_cast<uv_handle_t*>(handle)));
(*data)++; ++(*data);
uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr); uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr);
} }

View File

@ -12,30 +12,27 @@
// 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.
#ifndef CALLBACKS_H #ifndef CALLBACKS_H_
#define CALLBACKS_H #define CALLBACKS_H_
#include <uv.h> #include <uv.h>
extern "C" { extern "C" {
// idle-basic // idle-basic
void IdleCallback(uv_idle_t* handle);
void IdleCallback(uv_idle_t *handle);
// uvcat // uvcat
uv_fs_t open_req; uv_fs_t open_req;
uv_fs_t read_req; uv_fs_t read_req;
uv_fs_t write_req; uv_fs_t write_req;
void OnWrite(uv_fs_t* req);
void OnWrite(uv_fs_t *req); void OnRead(uv_fs_t* req);
void OnRead(uv_fs_t *req); void OnOpen(uv_fs_t* req);
void OnOpen(uv_fs_t *req);
// test_callback // test_callback
void TimerCallback(uv_timer_t* handle);
void TimerCallback(uv_timer_t *handle); } // extern "C"
}
#endif // CALLBACKS_H #endif // CALLBACKS_H_

View File

@ -1,9 +1,23 @@
# LibUV Sandbox Examples # LibUV Sandbox Examples
Each example in this folder is the sandboxed version of a code snippet from [LibUV's User Guide](https://docs.libuv.org/en/v1.x/guide.html). These examples perform some basic tasks using LibUV, and can be useful both to understand how to use LibUV Sandbox, 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
[LibUV's User Guide](https://docs.libuv.org/en/v1.x/guide.html). These examples
perform some basic tasks using LibUV, and can be useful both to understand how
to use LibUV Sandbox, but also to get an idea of how regular and sandboxed code
compare to each other.
This is the list of examples: This is the list of examples:
- **helloworld.cc**: sandboxed version of [helloworld/main.c](https://docs.libuv.org/en/v1.x/guide/basics.html#hello-world). It simply starts a loop that exits immediately. It shows how to run a simple loop in LibUV Sandbox. - **helloworld.cc**: sandboxed version of
- **idle-basic.cc**: sandboxed version of [idle-basic/main.c](https://docs.libuv.org/en/v1.x/guide/basics.html#handles-and-requests). Creates an idle watcher that stops the loop after a certain number of iterations. It shows how a simple callback can be used in LibUV Sandbox. [helloworld/main.c](https://docs.libuv.org/en/v1.x/guide/basics.html#hello-world).
- **uvcat.cc**: sandboxed version of [uvcat/main.c](http://docs.libuv.org/en/v1.x/guide/filesystem.html#reading-writing-files). Takes a single argument, the absolute path of a file, and prints its contents (it is a simplified version of the command line tootl `cat`). It shows how to manage various complex callbacks for opening, reading and writing files. It simply starts a loop that exits immediately. It shows how to run a simple
loop in LibUV Sandbox.
- **idle-basic.cc**: sandboxed version of
[idle-basic/main.c](https://docs.libuv.org/en/v1.x/guide/basics.html#handles-and-requests).
Creates an idle watcher that stops the loop after a certain number of
iterations. It shows how a simple callback can be used in LibUV Sandbox.
- **uvcat.cc**: sandboxed version of
[uvcat/main.c](http://docs.libuv.org/en/v1.x/guide/filesystem.html#reading-writing-files).
Takes a single argument, the absolute path of a file, and prints its contents
(it is a simplified version of the command line tootl `cat`). It shows how to
manage various complex callbacks for opening, reading and writing files.

View File

@ -21,7 +21,7 @@
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "uv_sapi.sapi.h" #include "uv_sapi.sapi.h"
class UVSapiHelloworldSandbox : public UVSandbox { class UVSapiHelloworldSandbox : public uv::UVSandbox {
private: private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override { sandbox2::PolicyBuilder*) override {
@ -35,57 +35,51 @@ class UVSapiHelloworldSandbox : public UVSandbox {
} }
}; };
int main(int argc, char* argv[]) { absl::Status HelloWorld() {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
absl::Status status;
// Initialize sandbox2 and sapi // Initialize sandbox2 and sapi
UVSapiHelloworldSandbox sandbox; UVSapiHelloworldSandbox sandbox;
status = sandbox.Init(); SAPI_RETURN_IF_ERROR(sandbox.Init());
if (!status.ok()) { uv::UVApi api(&sandbox);
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
}
UVApi api(&sandbox);
// Allocate memory for the uv_loop_t object // Allocate memory for the uv_loop_t object
void* loop_voidptr; void* loop_voidptr;
status = sandbox.rpc_channel()->Allocate(sizeof(uv_loop_t), &loop_voidptr); SAPI_RETURN_IF_ERROR(
if (!status.ok()) { sandbox.rpc_channel()->Allocate(sizeof(uv_loop_t), &loop_voidptr));
LOG(FATAL) << "sapi::Sandbox::rpc_channel()->Allocate failed: " << status;
}
sapi::v::RemotePtr loop(loop_voidptr); sapi::v::RemotePtr loop(loop_voidptr);
absl::StatusOr<int> return_code; int return_code;
// Initialize loop // Initialize loop
return_code = api.sapi_uv_loop_init(&loop); SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_loop_init(&loop));
if (!return_code.ok()) { if (return_code != 0) {
LOG(FATAL) << "sapi_uv_loop_init failed: " << return_code.status(); return absl::UnavailableError("uv_loop_init returned error " + return_code);
}
if (return_code.value() != 0) {
LOG(FATAL) << "uv_loop_init returned error " << return_code.value();
} }
std::cout << "The loop is about to quit" << std::endl; std::cout << "The loop is about to quit" << std::endl;
// Run loop // Run loop
return_code = api.sapi_uv_run(&loop, UV_RUN_DEFAULT); SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_run(&loop, UV_RUN_DEFAULT));
if (!return_code.ok()) { if (return_code != 0) {
LOG(FATAL) << "sapi_uv_run failed: " << return_code.status(); return absl::UnavailableError("uv_run returned error " + return_code);
}
if (return_code.value() != 0) {
LOG(FATAL) << "uv_run returned error " << return_code.value();
} }
// Close loop // Close loop
return_code = api.sapi_uv_loop_close(&loop); SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_loop_close(&loop));
if (!return_code.ok()) { if (return_code != 0) {
LOG(FATAL) << "sapi_uv_loop_close failed: " << return_code.status(); return absl::UnavailableError("uv_loop_close returned error " +
return_code);
} }
if (return_code.value() != 0) {
LOG(FATAL) << "uv_loop_close returned error " << return_code.value(); return absl::OkStatus();
}
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
if (absl::Status status = HelloWorld(); !status.ok()) {
LOG(ERROR) << "HelloWorld failed: " << status.ToString();
return EXIT_FAILURE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -21,7 +21,7 @@
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "uv_sapi.sapi.h" #include "uv_sapi.sapi.h"
class UVSapiIdleBasicSandbox : public UVSandbox { class UVSapiIdleBasicSandbox : public uv::UVSandbox {
private: private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override { sandbox2::PolicyBuilder*) override {
@ -36,88 +36,74 @@ class UVSapiIdleBasicSandbox : public UVSandbox {
} }
}; };
int main(int argc, char* argv[]) { absl::Status IdleBasic() {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
absl::Status status;
// Initialize sandbox2 and sapi // Initialize sandbox2 and sapi
UVSapiIdleBasicSandbox sandbox; UVSapiIdleBasicSandbox sandbox;
status = sandbox.Init(); SAPI_RETURN_IF_ERROR(sandbox.Init());
if (!status.ok()) { uv::UVApi api(&sandbox);
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
}
UVApi api(&sandbox);
// Get remote pointer to the IdleCallback method // Get remote pointer to the IdleCallback method
void* function_ptr; void* function_ptr;
status = sandbox.rpc_channel()->Symbol("IdleCallback", &function_ptr); SAPI_RETURN_IF_ERROR(
if (!status.ok()) { sandbox.rpc_channel()->Symbol("IdleCallback", &function_ptr));
LOG(FATAL) << "sapi::Sandbox::rpc_channel()->Symbol failed: " << status;
}
sapi::v::RemotePtr idle_callback(function_ptr); sapi::v::RemotePtr idle_callback(function_ptr);
// Allocate memory for the uv_idle_t object // Allocate memory for the uv_idle_t object
void* idle_voidptr; void* idle_voidptr;
status = sandbox.rpc_channel()->Allocate(sizeof(uv_idle_t), &idle_voidptr); SAPI_RETURN_IF_ERROR(
if (!status.ok()) { sandbox.rpc_channel()->Allocate(sizeof(uv_idle_t), &idle_voidptr));
LOG(FATAL) << "sapi::Sandbox::rpc_channel()->Allocate failed: " << status;
}
sapi::v::RemotePtr idler(idle_voidptr); sapi::v::RemotePtr idler(idle_voidptr);
absl::StatusOr<int> return_code; int return_code;
// Get default loop // Get default loop
absl::StatusOr<void*> loop_voidptr = api.sapi_uv_default_loop(); SAPI_ASSIGN_OR_RETURN(void* loop_voidptr, api.sapi_uv_default_loop());
if (!loop_voidptr.ok()) { sapi::v::RemotePtr loop(loop_voidptr);
LOG(FATAL) << "sapi_uv_default_loop failed: " << loop_voidptr.status();
}
sapi::v::RemotePtr loop(loop_voidptr.value());
// Initialize idler // Initialize idler
return_code = api.sapi_uv_idle_init(&loop, &idler); SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_idle_init(&loop, &idler));
if (!return_code.ok()) { if (return_code != 0) {
LOG(FATAL) << "sapi_uv_idle_init failed: " << return_code.status(); return absl::UnavailableError("sapi_uv_idle_init returned error " +
} return_code);
if (return_code.value() != 0) {
LOG(FATAL) << "sapi_uv_idle_init returned error " << return_code.value();
} }
// Start idler // Start idler
return_code = api.sapi_uv_idle_start(&idler, &idle_callback); SAPI_ASSIGN_OR_RETURN(return_code,
if (!return_code.ok()) { api.sapi_uv_idle_start(&idler, &idle_callback));
LOG(FATAL) << "sapi_uv_idle_start failed: " << return_code.status(); if (return_code != 0) {
} return absl::UnavailableError("sapi_uv_idle_start returned error " +
if (return_code.value() != 0) { return_code);
LOG(FATAL) << "sapi_uv_idle_start returned error " << return_code.value();
} }
// Run loop // Run loop
return_code = api.sapi_uv_run(&loop, UV_RUN_DEFAULT); SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_run(&loop, UV_RUN_DEFAULT));
if (!return_code.ok()) { if (return_code != 0) {
LOG(FATAL) << "sapi_uv_run failed: " << return_code.status(); return absl::UnavailableError("uv_run returned error " + return_code);
}
if (return_code.value() != 0) {
LOG(FATAL) << "uv_run returned error " << return_code.value();
} }
// Close idler // Close idler
sapi::v::NullPtr null_ptr; sapi::v::NullPtr null_ptr;
status = api.sapi_uv_close(&idler, &null_ptr); SAPI_RETURN_IF_ERROR(api.sapi_uv_close(&idler, &null_ptr));
if (!status.ok()) {
LOG(FATAL) << "sapi_uv_close failed: " << status;
}
// Close loop // Close loop
return_code = api.sapi_uv_loop_close(&loop); SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_loop_close(&loop));
if (!return_code.ok()) {
LOG(FATAL) << "sapi_uv_loop_close failed: " << return_code.status();
}
// UV_EBUSY is accepted because it is the return code of uv_loop_close // UV_EBUSY is accepted because it is the return code of uv_loop_close
// in the original example // in the original example
if (return_code.value() != 0 && return_code.value() != UV_EBUSY) { if (return_code != 0 && return_code != UV_EBUSY) {
LOG(FATAL) << "uv_loop_close returned error " << return_code.value(); return absl::UnavailableError("uv_loop_close returned error " +
return_code);
}
return absl::OkStatus();
}
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
if (absl::Status status = IdleBasic(); !status.ok()) {
LOG(ERROR) << "IdleBasic failed: " << status.ToString();
return EXIT_FAILURE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -21,7 +21,7 @@
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "uv_sapi.sapi.h" #include "uv_sapi.sapi.h"
class UVSapiUVCatSandbox : public UVSandbox { class UVSapiUVCatSandbox : public uv::UVSandbox {
public: public:
UVSapiUVCatSandbox(std::string filename) : filename(filename) {} UVSapiUVCatSandbox(std::string filename) : filename(filename) {}
@ -46,74 +46,62 @@ class UVSapiUVCatSandbox : public UVSandbox {
std::string filename; std::string filename;
}; };
absl::Status UVCat(std::string filearg) {
// Initialize sandbox2 and sapi
UVSapiUVCatSandbox sandbox(filearg);
SAPI_RETURN_IF_ERROR(sandbox.Init());
uv::UVApi api(&sandbox);
// Get remote pointer to the OnOpen method
void* function_ptr;
SAPI_RETURN_IF_ERROR(sandbox.rpc_channel()->Symbol("OnOpen", &function_ptr));
sapi::v::RemotePtr on_open(function_ptr);
// Get remote pointer to the open_req variable
void* open_req_voidptr;
SAPI_RETURN_IF_ERROR(
sandbox.rpc_channel()->Symbol("open_req", &open_req_voidptr));
sapi::v::RemotePtr open_req(open_req_voidptr);
// Get default loop
SAPI_ASSIGN_OR_RETURN(void* loop_voidptr, api.sapi_uv_default_loop());
sapi::v::RemotePtr loop(loop_voidptr);
int return_code;
// Open file using the OnOpen callback (which will also read and print it)
sapi::v::ConstCStr filename(filearg.c_str());
SAPI_ASSIGN_OR_RETURN(
return_code, api.sapi_uv_fs_open(&loop, &open_req, filename.PtrBefore(),
O_RDONLY, 0, &on_open));
if (return_code != 0) {
return absl::UnavailableError("uv_fs_open returned error " + return_code);
}
// Run loop
SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_run(&loop, UV_RUN_DEFAULT));
if (return_code != 0) {
return absl::UnavailableError("uv_run returned error " + return_code);
}
// Cleanup the request
SAPI_RETURN_IF_ERROR(api.sapi_uv_fs_req_cleanup(&open_req));
return absl::OkStatus();
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);
if (argc != 2) { if (argc != 2) {
LOG(FATAL) << "wrong number of arguments (1 expected)"; LOG(ERROR) << "wrong number of arguments (1 expected)";
} return EXIT_FAILURE;
std::string filename_str = argv[1];
absl::Status status;
// Initialize sandbox2 and sapi
UVSapiUVCatSandbox sandbox(filename_str);
status = sandbox.Init();
if (!status.ok()) {
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
}
UVApi api(&sandbox);
// Get remote pointer to the OnOpen method
void* function_ptr;
status = sandbox.rpc_channel()->Symbol("OnOpen", &function_ptr);
if (!status.ok()) {
LOG(FATAL) << "sapi::Sandbox::rpc_channel()->Symbol failed: " << status;
}
sapi::v::RemotePtr on_open(function_ptr);
// Get remote pointer to the open_req variable
void* open_req_voidptr;
status = sandbox.rpc_channel()->Symbol("open_req", &open_req_voidptr);
if (!status.ok()) {
LOG(FATAL) << "sapi::Sandbox::rpc_channel()->Symbol failed: " << status;
}
sapi::v::RemotePtr open_req(open_req_voidptr);
// Get default loop
absl::StatusOr<void*> loop_voidptr = api.sapi_uv_default_loop();
if (!loop_voidptr.ok()) {
LOG(FATAL) << "sapi_uv_default_loop failed: " << loop_voidptr.status();
}
sapi::v::RemotePtr loop(loop_voidptr.value());
absl::StatusOr<int> return_code;
// Open file using the OnOpen callback (which will also read and print it)
sapi::v::ConstCStr filename(filename_str.c_str());
return_code = api.sapi_uv_fs_open(&loop, &open_req, filename.PtrBefore(),
O_RDONLY, 0, &on_open);
if (!return_code.ok()) {
LOG(FATAL) << "sapi_uv_fs_open failed: " << return_code.status();
}
if (return_code.value() != 0) {
LOG(FATAL) << "uv_fs_open returned error " << return_code.value();
} }
// Run loop if (absl::Status status = UVCat(argv[1]); !status.ok()) {
return_code = api.sapi_uv_run(&loop, UV_RUN_DEFAULT); LOG(ERROR) << "UVCat failed: " << status.ToString();
if (!return_code.ok()) { return EXIT_FAILURE;
LOG(FATAL) << "sapi_uv_run failed: " << return_code.status();
}
if (return_code.value() != 0) {
LOG(FATAL) << "uv_run returned error " << return_code.value();
}
// Cleanup the request
status = api.sapi_uv_fs_req_cleanup(&open_req);
if (!status.ok()) {
LOG(FATAL) << "sapi_uv_fs_req_cleanup failed: " << status;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -11,14 +11,20 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# 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.
"""Script generating a wrapper API for LibUV."""
"""Script generating a wrapper API for LibUV.
.. note::
This scriptis highly specific to LibUV's source code
and does not generalize to any other library
"""
import sys import sys
from typing import List
import re import re
import os import os
def get_var_type(string): def get_var_type(string : str) -> str:
"""Gets the type from an argument variable """Gets the type from an argument variable
(e.g. "int x" -> "int") (e.g. "int x" -> "int")
""" """
@ -32,7 +38,7 @@ def get_var_type(string):
return " ".join(var.split(" ")[:-1]).strip() return " ".join(var.split(" ")[:-1]).strip()
def get_var_name(string): def get_var_name(string : str) -> str:
"""Gets the name from an argument variable """Gets the name from an argument variable
(e.g. "int x" -> "x") (e.g. "int x" -> "x")
""" """
@ -50,7 +56,7 @@ def get_var_name(string):
return var.split(" ")[-1].strip() return var.split(" ")[-1].strip()
def fix_method_type(string): def fix_method_type(string : str) -> str:
"""Fixes the method type """Fixes the method type
(e.g. "const int*" -> "const void*") (e.g. "const int*" -> "const void*")
""" """
@ -69,7 +75,7 @@ def fix_method_type(string):
return method_type return method_type
def fix_argument(string): def fix_argument(string : str) -> str:
"""Fixes an argument """Fixes an argument
(e.g. "const int* x" -> "const void* x") (e.g. "const int* x" -> "const void* x")
""" """
@ -92,7 +98,7 @@ def fix_argument(string):
return arg_type + " " + arg_name return arg_type + " " + arg_name
def fix_call_argument(string): def fix_call_argument(string : str) -> str:
"""Fixes an argument in a call the orignal method """Fixes an argument in a call the orignal method
(e.g. "const int* x" -> "reinterpret_cast<const int*>(x)") (e.g. "const int* x" -> "reinterpret_cast<const int*>(x)")
""" """
@ -113,14 +119,14 @@ def fix_call_argument(string):
return arg_name return arg_name
def read_file(filename): def read_file(filename : str) -> str:
"""Returns contents of filename as a string""" """Returns contents of filename as a string"""
file = open(filename, "r") file = open(filename, "r")
return str(file.read()) return str(file.read())
def clean_file(text): def clean_file(text : str) -> str:
"""Prepares the file for parsing """Prepares the file for parsing
In particular, removes comments and macros from text In particular, removes comments and macros from text
Additionally, moves pointer asterisks next to its type Additionally, moves pointer asterisks next to its type
@ -134,7 +140,7 @@ def clean_file(text):
return result return result
def get_signatures(text): def get_signatures(text : str) -> str:
"""Gets the signatures of all the methods in the header """Gets the signatures of all the methods in the header
.. note:: This method only works on a certain version of LibUV's header .. note:: This method only works on a certain version of LibUV's header
""" """
@ -148,71 +154,78 @@ def get_signatures(text):
return zip(method_types, names, arguments_lists) return zip(method_types, names, arguments_lists)
def write_method(method_type, name, arguments_list, header, source): def append_method(method_type : str, name : str, arguments_list : List[str],
"""Writes the method to both the header and the source files""" header : List[str], source : List[str]) -> None:
"""Writes the method to the header and the source list of lines"""
header.write(fix_method_type(method_type) + " sapi_" + name + "(" + header.append(fix_method_type(method_type) + " sapi_" + name + "(" +
", ".join(map(fix_argument, arguments_list)) + ");\n\n") ", ".join(map(fix_argument, arguments_list)) + ");")
source.write(fix_method_type(method_type) + " sapi_" + name + "(" + source.append(fix_method_type(method_type) + " sapi_" + name + "(" +
", ".join(map(fix_argument, arguments_list)) + ") {\n") ", ".join(map(fix_argument, arguments_list)) + ") {\n" +
source.write(" return " + name + "(" + " return " + name + "(" +
", ".join(map(fix_call_argument, arguments_list)) + ");\n") ", ".join(map(fix_call_argument, arguments_list)) + ");\n" +
source.write("}\n\n") "}")
def write_text(text, file): def append_text(text : str, file : List[str]) -> None:
"""Writes text to file """Writes text to file list of lines
Useful for additional methods, includes, extern "C"... Useful for additional methods, includes, extern "C"...
""" """
file.write(text) file.append(text)
def generate_wrapper(): def generate_wrapper() -> None:
"""Generates the wrapper""" """Generates the wrapper"""
header_file = open(sys.argv[2], "w")
source_file = open(sys.argv[3], "w")
text = read_file(sys.argv[1]) text = read_file(sys.argv[1])
text = clean_file(text) text = clean_file(text)
signatures = get_signatures(text) signatures = get_signatures(text)
header = open(sys.argv[2], "w") header = []
source = open(sys.argv[3], "w") source = []
write_text("#include <uv.h>\n\n", header) append_text("#include <uv.h>", header)
write_text("extern \"C\" {\n\n", header) append_text("extern \"C\" {", header)
write_text("#include \"" + os.path.abspath(header.name) + "\"\n\n", source) append_text("#include \"" + os.path.abspath(header_file.name) + "\"", source)
for (method_type, name, arguments_list) in signatures: for (method_type, name, arguments_list) in signatures:
# These wrapper methods are manually added at the end # These wrapper methods are manually added at the end
if name in ("uv_once", "uv_loop_configure"): if name in ("uv_once", "uv_loop_configure"):
continue continue
write_method(method_type, name, arguments_list, header, source) append_method(method_type, name, arguments_list, header, source)
# Add sapi_uv_once (uv_once uses a differnet kind of callback) # Add sapi_uv_once (uv_once uses a differnet kind of callback)
write_text("void sapi_uv_once(void* guard, void (*callback)(void));\n\n", append_text("void sapi_uv_once(void* guard, void (*callback)(void));",
header) header)
write_text("void sapi_uv_once(void* guard, void (*callback)(void)) {\n" + append_text("void sapi_uv_once(void* guard, void (*callback)(void)) {\n" +
" return uv_once(reinterpret_cast<uv_once_t*>(guard)," + " return uv_once(reinterpret_cast<uv_once_t*>(guard)," +
"callback);\n" + "}\n\n", source) "callback);\n" + "}", source)
# Add sapi_uv_loop_configure (uv_loop_configure is variadic) # Add sapi_uv_loop_configure (uv_loop_configure is variadic)
write_text("int sapi_uv_loop_configure(void* loop, uv_loop_option option)" + append_text("int sapi_uv_loop_configure(void* loop, uv_loop_option option)" +
";\n\n", header) ";", header)
write_text("int sapi_uv_loop_configure(void* loop, uv_loop_option option)" + append_text("int sapi_uv_loop_configure(void* loop, uv_loop_option option)" +
" {\n return uv_loop_configure(" + " {\n return uv_loop_configure(" +
"reinterpret_cast<uv_loop_t*>(loop), option);\n" + "}\n\n", "reinterpret_cast<uv_loop_t*>(loop), option);\n" + "}",
source) source)
# Add sapi_uv_loop_configure_int (uv_loop_configure is variadic) # Add sapi_uv_loop_configure_int (uv_loop_configure is variadic)
write_text("int sapi_uv_loop_configure_int(void* loop, " + append_text("int sapi_uv_loop_configure_int(void* loop, " +
"uv_loop_option option, int ap);\n\n", header) "uv_loop_option option, int ap);", header)
write_text("int sapi_uv_loop_configure_int(void* loop, " + append_text("int sapi_uv_loop_configure_int(void* loop, " +
"uv_loop_option option, int ap) {\n" + "uv_loop_option option, int ap) {\n" +
" return uv_loop_configure(" + " return uv_loop_configure(" +
"reinterpret_cast<uv_loop_t*>(loop), option, ap);\n}\n\n", "reinterpret_cast<uv_loop_t*>(loop), option, ap);\n}",
source) source)
write_text("} // extern \"C\"\n", header) append_text("} // extern \"C\"\n", header)
header_file.write("\n\n".join(header))
source_file.write("\n\n".join(source))
generate_wrapper() generate_wrapper()

View File

@ -21,7 +21,9 @@
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
#include "uv_sapi.sapi.h" #include "uv_sapi.sapi.h"
class UVTestArraySapiSandbox : public UVSandbox { namespace {
class UVTestArraySapiSandbox : public uv::UVSandbox {
private: private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override { sandbox2::PolicyBuilder*) override {
@ -40,12 +42,12 @@ class UVTestArray : public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
sandbox_ = std::make_unique<UVTestArraySapiSandbox>(); sandbox_ = std::make_unique<UVTestArraySapiSandbox>();
ASSERT_THAT(sandbox_->Init(), ::sapi::IsOk()); ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
api_ = std::make_unique<UVApi>(sandbox_.get()); api_ = std::make_unique<uv::UVApi>(sandbox_.get());
} }
std::unique_ptr<UVTestArraySapiSandbox> sandbox_; std::unique_ptr<UVTestArraySapiSandbox> sandbox_;
std::unique_ptr<UVApi> api_; std::unique_ptr<uv::UVApi> api_;
}; };
TEST_F(UVTestArray, LoadAvg) { TEST_F(UVTestArray, LoadAvg) {
@ -65,3 +67,5 @@ TEST_F(UVTestArray, LoadAvg) {
ASSERT_GE(avg_buf[1], 0); ASSERT_GE(avg_buf[1], 0);
ASSERT_GE(avg_buf[2], 0); ASSERT_GE(avg_buf[2], 0);
} }
} // namespace

View File

@ -21,7 +21,9 @@
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
#include "uv_sapi.sapi.h" #include "uv_sapi.sapi.h"
class UVTestCallbackSapiSandbox : public UVSandbox { namespace {
class UVTestCallbackSapiSandbox : public uv::UVSandbox {
private: private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override { sandbox2::PolicyBuilder*) override {
@ -40,8 +42,8 @@ class UVTestCallback : public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
sandbox_ = std::make_unique<UVTestCallbackSapiSandbox>(); sandbox_ = std::make_unique<UVTestCallbackSapiSandbox>();
ASSERT_THAT(sandbox_->Init(), ::sapi::IsOk()); ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
api_ = std::make_unique<UVApi>(sandbox_.get()); api_ = std::make_unique<uv::UVApi>(sandbox_.get());
} }
// Check sapi_uv_timer_init // Check sapi_uv_timer_init
@ -87,7 +89,7 @@ class UVTestCallback : public ::testing::Test {
} }
std::unique_ptr<UVTestCallbackSapiSandbox> sandbox_; std::unique_ptr<UVTestCallbackSapiSandbox> sandbox_;
std::unique_ptr<UVApi> api_; std::unique_ptr<uv::UVApi> api_;
static constexpr int kData = 1729; static constexpr int kData = 1729;
}; };
@ -137,3 +139,5 @@ TEST_F(UVTestCallback, TimerCallback) {
UVDefaultLoop(&loop); UVDefaultLoop(&loop);
UVLoopClose(loop.PtrNone()); UVLoopClose(loop.PtrNone());
} }
} // namespace

View File

@ -20,7 +20,9 @@
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
#include "uv_sapi.sapi.h" #include "uv_sapi.sapi.h"
class UVTestErrorSapiSandbox : public UVSandbox { namespace {
class UVTestErrorSapiSandbox : public uv::UVSandbox {
private: private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override { sandbox2::PolicyBuilder*) override {
@ -37,8 +39,8 @@ class UVTestError : public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
sandbox_ = std::make_unique<UVTestErrorSapiSandbox>(); sandbox_ = std::make_unique<UVTestErrorSapiSandbox>();
ASSERT_THAT(sandbox_->Init(), ::sapi::IsOk()); ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
api_ = std::make_unique<UVApi>(sandbox_.get()); api_ = std::make_unique<uv::UVApi>(sandbox_.get());
} }
// Check sapi_uv_strerror on error // Check sapi_uv_strerror on error
@ -67,7 +69,7 @@ class UVTestError : public ::testing::Test {
} }
std::unique_ptr<UVTestErrorSapiSandbox> sandbox_; std::unique_ptr<UVTestErrorSapiSandbox> sandbox_;
std::unique_ptr<UVApi> api_; std::unique_ptr<uv::UVApi> api_;
}; };
TEST_F(UVTestError, ErrorMessage) { TEST_F(UVTestError, ErrorMessage) {
@ -88,3 +90,5 @@ TEST_F(UVTestError, SystemError) {
UVTranslateSysError(UV_EACCES); UVTranslateSysError(UV_EACCES);
UVTranslateSysError(0); UVTranslateSysError(0);
} }
} // namespace

View File

@ -21,7 +21,9 @@
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
#include "uv_sapi.sapi.h" #include "uv_sapi.sapi.h"
class UVTestLoopSapiSandbox : public UVSandbox { namespace {
class UVTestLoopSapiSandbox : public uv::UVSandbox {
private: private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override { sandbox2::PolicyBuilder*) override {
@ -39,8 +41,8 @@ class UVTestLoop : public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
sandbox_ = std::make_unique<UVTestLoopSapiSandbox>(); sandbox_ = std::make_unique<UVTestLoopSapiSandbox>();
ASSERT_THAT(sandbox_->Init(), ::sapi::IsOk()); ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
api_ = std::make_unique<UVApi>(sandbox_.get()); api_ = std::make_unique<uv::UVApi>(sandbox_.get());
} }
// Check sapi_uv_loop_init // Check sapi_uv_loop_init
@ -69,7 +71,7 @@ class UVTestLoop : public ::testing::Test {
} }
std::unique_ptr<UVTestLoopSapiSandbox> sandbox_; std::unique_ptr<UVTestLoopSapiSandbox> sandbox_;
std::unique_ptr<UVApi> api_; std::unique_ptr<uv::UVApi> api_;
}; };
TEST_F(UVTestLoop, InitLoop) { TEST_F(UVTestLoop, InitLoop) {
@ -100,3 +102,5 @@ TEST_F(UVTestLoop, DefaultLoop) {
UVDefaultLoop(&loop); UVDefaultLoop(&loop);
UVLoopClose(loop.PtrNone()); UVLoopClose(loop.PtrNone());
} }
} // namespace

View File

@ -21,7 +21,9 @@
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
#include "uv_sapi.sapi.h" #include "uv_sapi.sapi.h"
class UVTestOSSapiSandbox : public UVSandbox { namespace {
class UVTestOSSapiSandbox : public uv::UVSandbox {
private: private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override { sandbox2::PolicyBuilder*) override {
@ -43,12 +45,12 @@ class UVTestOS : public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
sandbox_ = std::make_unique<UVTestOSSapiSandbox>(); sandbox_ = std::make_unique<UVTestOSSapiSandbox>();
ASSERT_THAT(sandbox_->Init(), ::sapi::IsOk()); ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
api_ = std::make_unique<UVApi>(sandbox_.get()); api_ = std::make_unique<uv::UVApi>(sandbox_.get());
} }
std::unique_ptr<UVTestOSSapiSandbox> sandbox_; std::unique_ptr<UVTestOSSapiSandbox> sandbox_;
std::unique_ptr<UVApi> api_; std::unique_ptr<uv::UVApi> api_;
static constexpr size_t kBigBufLen = 4096; static constexpr size_t kBigBufLen = 4096;
static constexpr size_t kSmallBufLen = 1; static constexpr size_t kSmallBufLen = 1;
@ -131,3 +133,5 @@ TEST_F(UVTestOS, TmpDirSmall) {
// Test error code is as expected // Test error code is as expected
ASSERT_EQ(error_code, expected_error_code); ASSERT_EQ(error_code, expected_error_code);
} }
} // namespace