mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Merge pull request #55 from FedericoStazi:libuv
PiperOrigin-RevId: 343278766 Change-Id: I708fdc1cd98d5fbb2abcf3261d1cecd65cec46fe
This commit is contained in:
commit
e6bb05a15d
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -16,3 +16,6 @@
|
|||
[submodule "oss-internship-2020/curl/curl_wrapper/curl"]
|
||||
path = oss-internship-2020/curl/curl_wrapper/curl
|
||||
url = git@github.com:curl/curl.git
|
||||
[submodule "oss-internship-2020/libuv/libuv"]
|
||||
path = oss-internship-2020/libuv/libuv
|
||||
url = git@github.com:libuv/libuv.git
|
||||
|
|
1
oss-internship-2020/libuv/.gitignore
vendored
Normal file
1
oss-internship-2020/libuv/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
build/
|
394
oss-internship-2020/libuv/CMakeLists.txt
Normal file
394
oss-internship-2020/libuv/CMakeLists.txt
Normal file
|
@ -0,0 +1,394 @@
|
|||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
project(libuv_sandbox)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
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")
|
||||
add_custom_command(
|
||||
|
||||
OUTPUT "${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.h"
|
||||
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.cc"
|
||||
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
|
||||
COMMAND "${SAPI_PYTHON3_EXECUTABLE}"
|
||||
"generator/wrapper_generator.py"
|
||||
"libuv/include/uv.h"
|
||||
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.h"
|
||||
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.cc"
|
||||
|
||||
COMMENT "Generate the wrapper header and source files"
|
||||
)
|
||||
|
||||
option(SAPI_UV_ENABLE_EXAMPLES "" ON)
|
||||
option(SAPI_UV_ENABLE_TESTS "" ON)
|
||||
|
||||
# Add callbacks used by examples and tests
|
||||
if (SAPI_UV_ENABLE_EXAMPLES OR SAPI_UV_ENABLE_TESTS)
|
||||
list(APPEND SAPI_UV_CALLBACKS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.cc"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Wrapper library including wrappers for all libuv methods and callbacks
|
||||
# The SAPI_UV_CALLBACKS variable should contain the absolute paths of
|
||||
# all the files implementing the callbacks
|
||||
add_library(uv_wrapper_and_callbacks OBJECT
|
||||
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.h"
|
||||
"${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.cc"
|
||||
"${SAPI_UV_CALLBACKS}"
|
||||
)
|
||||
set_target_properties(uv_wrapper_and_callbacks
|
||||
PROPERTIES LINKER_LANGUAGE C
|
||||
)
|
||||
|
||||
# Link the wrapper to the original uv library
|
||||
add_subdirectory(libuv)
|
||||
target_link_libraries(uv_wrapper_and_callbacks uv_a)
|
||||
|
||||
# Setup Sandboxed API
|
||||
set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree")
|
||||
set(SAPI_ENABLE_EXAMPLES ${SAPI_UV_ENABLE_EXAMPLES} CACHE BOOL "" FORCE)
|
||||
set(SAPI_ENABLE_TESTS ${SAPI_UV_ENABLE_TESTS} CACHE BOOL "" FORCE)
|
||||
|
||||
# Generate SAPI header
|
||||
add_sapi_library(uv_sapi
|
||||
|
||||
# List of all the generated methods
|
||||
FUNCTIONS sapi_uv_accept
|
||||
sapi_uv_async_init
|
||||
sapi_uv_async_send
|
||||
sapi_uv_backend_fd
|
||||
sapi_uv_backend_timeout
|
||||
sapi_uv_barrier_destroy
|
||||
sapi_uv_barrier_init
|
||||
sapi_uv_barrier_wait
|
||||
# TODO(cblichmann): sapi_uv_buf_init
|
||||
sapi_uv_cancel
|
||||
sapi_uv_chdir
|
||||
sapi_uv_check_init
|
||||
sapi_uv_check_start
|
||||
sapi_uv_check_stop
|
||||
sapi_uv_close
|
||||
sapi_uv_cond_broadcast
|
||||
sapi_uv_cond_destroy
|
||||
sapi_uv_cond_init
|
||||
sapi_uv_cond_signal
|
||||
sapi_uv_cond_timedwait
|
||||
sapi_uv_cond_wait
|
||||
sapi_uv_cpu_info
|
||||
sapi_uv_cwd
|
||||
sapi_uv_default_loop
|
||||
sapi_uv_disable_stdio_inheritance
|
||||
sapi_uv_dlclose
|
||||
sapi_uv_dlerror
|
||||
sapi_uv_dlopen
|
||||
sapi_uv_dlsym
|
||||
sapi_uv_err_name
|
||||
sapi_uv_err_name_r
|
||||
sapi_uv_exepath
|
||||
sapi_uv_fileno
|
||||
sapi_uv_free_cpu_info
|
||||
sapi_uv_free_interface_addresses
|
||||
sapi_uv_freeaddrinfo
|
||||
sapi_uv_fs_access
|
||||
sapi_uv_fs_chmod
|
||||
sapi_uv_fs_chown
|
||||
sapi_uv_fs_close
|
||||
sapi_uv_fs_closedir
|
||||
sapi_uv_fs_copyfile
|
||||
sapi_uv_fs_event_getpath
|
||||
sapi_uv_fs_event_init
|
||||
sapi_uv_fs_event_start
|
||||
sapi_uv_fs_event_stop
|
||||
sapi_uv_fs_fchmod
|
||||
sapi_uv_fs_fchown
|
||||
sapi_uv_fs_fdatasync
|
||||
sapi_uv_fs_fstat
|
||||
sapi_uv_fs_fsync
|
||||
sapi_uv_fs_ftruncate
|
||||
sapi_uv_fs_futime
|
||||
sapi_uv_fs_get_path
|
||||
sapi_uv_fs_get_ptr
|
||||
sapi_uv_fs_get_result
|
||||
sapi_uv_fs_get_statbuf
|
||||
sapi_uv_fs_get_system_error
|
||||
sapi_uv_fs_get_type
|
||||
sapi_uv_fs_lchown
|
||||
sapi_uv_fs_link
|
||||
sapi_uv_fs_lstat
|
||||
sapi_uv_fs_lutime
|
||||
sapi_uv_fs_mkdir
|
||||
sapi_uv_fs_mkdtemp
|
||||
sapi_uv_fs_mkstemp
|
||||
sapi_uv_fs_open
|
||||
sapi_uv_fs_opendir
|
||||
sapi_uv_fs_poll_getpath
|
||||
sapi_uv_fs_poll_init
|
||||
sapi_uv_fs_poll_start
|
||||
sapi_uv_fs_poll_stop
|
||||
sapi_uv_fs_read
|
||||
sapi_uv_fs_readdir
|
||||
sapi_uv_fs_readlink
|
||||
sapi_uv_fs_realpath
|
||||
sapi_uv_fs_rename
|
||||
sapi_uv_fs_req_cleanup
|
||||
sapi_uv_fs_rmdir
|
||||
sapi_uv_fs_scandir
|
||||
sapi_uv_fs_scandir_next
|
||||
sapi_uv_fs_sendfile
|
||||
sapi_uv_fs_stat
|
||||
sapi_uv_fs_statfs
|
||||
sapi_uv_fs_symlink
|
||||
sapi_uv_fs_unlink
|
||||
sapi_uv_fs_utime
|
||||
sapi_uv_fs_write
|
||||
sapi_uv_get_constrained_memory
|
||||
sapi_uv_get_free_memory
|
||||
sapi_uv_get_osfhandle
|
||||
sapi_uv_get_process_title
|
||||
sapi_uv_get_total_memory
|
||||
sapi_uv_getaddrinfo
|
||||
sapi_uv_getnameinfo
|
||||
sapi_uv_getrusage
|
||||
sapi_uv_gettimeofday
|
||||
sapi_uv_guess_handle
|
||||
sapi_uv_handle_get_data
|
||||
sapi_uv_handle_get_loop
|
||||
sapi_uv_handle_get_type
|
||||
sapi_uv_handle_set_data
|
||||
sapi_uv_handle_size
|
||||
sapi_uv_handle_type_name
|
||||
sapi_uv_has_ref
|
||||
sapi_uv_hrtime
|
||||
sapi_uv_idle_init
|
||||
sapi_uv_idle_start
|
||||
sapi_uv_idle_stop
|
||||
sapi_uv_if_indextoiid
|
||||
sapi_uv_if_indextoname
|
||||
sapi_uv_inet_ntop
|
||||
sapi_uv_inet_pton
|
||||
sapi_uv_interface_addresses
|
||||
sapi_uv_ip4_addr
|
||||
sapi_uv_ip4_name
|
||||
sapi_uv_ip6_addr
|
||||
sapi_uv_ip6_name
|
||||
sapi_uv_is_active
|
||||
sapi_uv_is_closing
|
||||
sapi_uv_is_readable
|
||||
sapi_uv_is_writable
|
||||
sapi_uv_key_create
|
||||
sapi_uv_key_delete
|
||||
sapi_uv_key_get
|
||||
sapi_uv_key_set
|
||||
sapi_uv_kill
|
||||
sapi_uv_library_shutdown
|
||||
sapi_uv_listen
|
||||
sapi_uv_loadavg
|
||||
sapi_uv_loop_alive
|
||||
sapi_uv_loop_close
|
||||
sapi_uv_loop_configure
|
||||
sapi_uv_loop_configure_int
|
||||
sapi_uv_loop_delete
|
||||
sapi_uv_loop_fork
|
||||
sapi_uv_loop_get_data
|
||||
sapi_uv_loop_init
|
||||
sapi_uv_loop_new
|
||||
sapi_uv_loop_set_data
|
||||
sapi_uv_loop_size
|
||||
sapi_uv_metrics_idle_time
|
||||
sapi_uv_mutex_destroy
|
||||
sapi_uv_mutex_init
|
||||
sapi_uv_mutex_init_recursive
|
||||
sapi_uv_mutex_lock
|
||||
sapi_uv_mutex_trylock
|
||||
sapi_uv_mutex_unlock
|
||||
sapi_uv_now
|
||||
sapi_uv_once
|
||||
sapi_uv_open_osfhandle
|
||||
sapi_uv_os_environ
|
||||
sapi_uv_os_free_environ
|
||||
sapi_uv_os_free_passwd
|
||||
sapi_uv_os_get_passwd
|
||||
sapi_uv_os_getenv
|
||||
sapi_uv_os_gethostname
|
||||
sapi_uv_os_getpid
|
||||
sapi_uv_os_getppid
|
||||
sapi_uv_os_getpriority
|
||||
sapi_uv_os_homedir
|
||||
sapi_uv_os_setenv
|
||||
sapi_uv_os_setpriority
|
||||
sapi_uv_os_tmpdir
|
||||
sapi_uv_os_uname
|
||||
sapi_uv_os_unsetenv
|
||||
sapi_uv_pipe_bind
|
||||
sapi_uv_pipe_chmod
|
||||
sapi_uv_pipe_connect
|
||||
sapi_uv_pipe_getpeername
|
||||
sapi_uv_pipe_getsockname
|
||||
sapi_uv_pipe_init
|
||||
sapi_uv_pipe_open
|
||||
sapi_uv_pipe_pending_count
|
||||
sapi_uv_pipe_pending_instances
|
||||
sapi_uv_pipe_pending_type
|
||||
sapi_uv_poll_init
|
||||
sapi_uv_poll_init_socket
|
||||
sapi_uv_poll_start
|
||||
sapi_uv_poll_stop
|
||||
sapi_uv_prepare_init
|
||||
sapi_uv_prepare_start
|
||||
sapi_uv_prepare_stop
|
||||
sapi_uv_print_active_handles
|
||||
sapi_uv_print_all_handles
|
||||
sapi_uv_process_get_pid
|
||||
sapi_uv_process_kill
|
||||
sapi_uv_queue_work
|
||||
sapi_uv_random
|
||||
sapi_uv_read_start
|
||||
sapi_uv_read_stop
|
||||
sapi_uv_recv_buffer_size
|
||||
sapi_uv_ref
|
||||
sapi_uv_replace_allocator
|
||||
sapi_uv_req_get_data
|
||||
sapi_uv_req_get_type
|
||||
sapi_uv_req_set_data
|
||||
sapi_uv_req_size
|
||||
sapi_uv_req_type_name
|
||||
sapi_uv_resident_set_memory
|
||||
sapi_uv_run
|
||||
sapi_uv_rwlock_destroy
|
||||
sapi_uv_rwlock_init
|
||||
sapi_uv_rwlock_rdlock
|
||||
sapi_uv_rwlock_rdunlock
|
||||
sapi_uv_rwlock_tryrdlock
|
||||
sapi_uv_rwlock_trywrlock
|
||||
sapi_uv_rwlock_wrlock
|
||||
sapi_uv_rwlock_wrunlock
|
||||
sapi_uv_sem_destroy
|
||||
sapi_uv_sem_init
|
||||
sapi_uv_sem_post
|
||||
sapi_uv_sem_trywait
|
||||
sapi_uv_sem_wait
|
||||
sapi_uv_send_buffer_size
|
||||
sapi_uv_set_process_title
|
||||
sapi_uv_setup_args
|
||||
sapi_uv_shutdown
|
||||
sapi_uv_signal_init
|
||||
sapi_uv_signal_start
|
||||
sapi_uv_signal_start_oneshot
|
||||
sapi_uv_signal_stop
|
||||
sapi_uv_sleep
|
||||
sapi_uv_spawn
|
||||
sapi_uv_stop
|
||||
sapi_uv_stream_get_write_queue_size
|
||||
sapi_uv_stream_set_blocking
|
||||
sapi_uv_strerror
|
||||
sapi_uv_strerror_r
|
||||
sapi_uv_tcp_bind
|
||||
sapi_uv_tcp_close_reset
|
||||
sapi_uv_tcp_connect
|
||||
sapi_uv_tcp_getpeername
|
||||
sapi_uv_tcp_getsockname
|
||||
sapi_uv_tcp_init
|
||||
sapi_uv_tcp_init_ex
|
||||
sapi_uv_tcp_keepalive
|
||||
sapi_uv_tcp_nodelay
|
||||
sapi_uv_tcp_open
|
||||
sapi_uv_tcp_simultaneous_accepts
|
||||
sapi_uv_thread_create
|
||||
sapi_uv_thread_create_ex
|
||||
sapi_uv_thread_equal
|
||||
sapi_uv_thread_join
|
||||
sapi_uv_thread_self
|
||||
sapi_uv_timer_again
|
||||
sapi_uv_timer_get_due_in
|
||||
sapi_uv_timer_get_repeat
|
||||
sapi_uv_timer_init
|
||||
sapi_uv_timer_set_repeat
|
||||
sapi_uv_timer_start
|
||||
sapi_uv_timer_stop
|
||||
sapi_uv_translate_sys_error
|
||||
sapi_uv_try_write
|
||||
sapi_uv_tty_get_vterm_state
|
||||
sapi_uv_tty_get_winsize
|
||||
sapi_uv_tty_init
|
||||
sapi_uv_tty_reset_mode
|
||||
sapi_uv_tty_set_mode
|
||||
sapi_uv_tty_set_vterm_state
|
||||
sapi_uv_udp_bind
|
||||
sapi_uv_udp_connect
|
||||
sapi_uv_udp_get_send_queue_count
|
||||
sapi_uv_udp_get_send_queue_size
|
||||
sapi_uv_udp_getpeername
|
||||
sapi_uv_udp_getsockname
|
||||
sapi_uv_udp_init
|
||||
sapi_uv_udp_init_ex
|
||||
sapi_uv_udp_open
|
||||
sapi_uv_udp_recv_start
|
||||
sapi_uv_udp_recv_stop
|
||||
sapi_uv_udp_send
|
||||
sapi_uv_udp_set_broadcast
|
||||
sapi_uv_udp_set_membership
|
||||
sapi_uv_udp_set_multicast_interface
|
||||
sapi_uv_udp_set_multicast_loop
|
||||
sapi_uv_udp_set_multicast_ttl
|
||||
sapi_uv_udp_set_source_membership
|
||||
sapi_uv_udp_set_ttl
|
||||
sapi_uv_udp_try_send
|
||||
sapi_uv_udp_using_recvmmsg
|
||||
sapi_uv_unref
|
||||
sapi_uv_update_time
|
||||
sapi_uv_uptime
|
||||
sapi_uv_version
|
||||
sapi_uv_version_string
|
||||
sapi_uv_walk
|
||||
sapi_uv_write
|
||||
sapi_uv_write2
|
||||
|
||||
INPUTS "${CMAKE_BINARY_DIR}/uv_wrapper/uv_wrapper.h"
|
||||
|
||||
LIBRARY uv_wrapper_and_callbacks
|
||||
|
||||
LIBRARY_NAME UV
|
||||
|
||||
NAMESPACE uv
|
||||
)
|
||||
|
||||
# Include generated SAPI header
|
||||
target_include_directories(uv_sapi INTERFACE
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
# Add examples
|
||||
if (SAPI_UV_ENABLE_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# Add tests
|
||||
if (SAPI_UV_ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
93
oss-internship-2020/libuv/README.md
Normal file
93
oss-internship-2020/libuv/README.md
Normal file
|
@ -0,0 +1,93 @@
|
|||
# LibUV Sandbox
|
||||
|
||||
This library is a sandboxed version of [LibUV](https://libuv.org/), 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 `libuv/` directory, build the
|
||||
library:
|
||||
```
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -G Ninja -D SAPI_ROOT=[path to sandboxed-api]
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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`.
|
||||
|
||||
## 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).
|
||||
|
||||
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
|
||||
|
||||
The `tests` folder contains some test cases created using Google Test.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
The `callbacks.h` and `callbacks.cc` files in the `callbacks` folder implement
|
||||
all the callbacks used by examples and tests.
|
90
oss-internship-2020/libuv/callbacks/callbacks.cc
Normal file
90
oss-internship-2020/libuv/callbacks/callbacks.cc
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "callbacks.h" // NOLINT(build/include)
|
||||
|
||||
#include <iostream>
|
||||
|
||||
size_t g_iterations = 0;
|
||||
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
|
||||
void IdleCallback(uv_idle_t* handle) {
|
||||
++g_iterations;
|
||||
if (g_iterations > kMaxIterations) {
|
||||
std::cout << "IdleCallback was called " << kMaxIterations << " times"
|
||||
<< std::endl;
|
||||
uv_idle_stop(handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Called after some chars have been written
|
||||
// As soon as writing of these bytes is completed, read more
|
||||
void OnWrite(uv_fs_t* req) {
|
||||
if (req->result < 0) {
|
||||
std::cerr << "Write error: " << uv_strerror(static_cast<int>(req->result))
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
// 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
|
||||
// As soon as reading of these bytes is completed, write them
|
||||
void OnRead(uv_fs_t* req) {
|
||||
if (req->result < 0) {
|
||||
std::cerr << "Read error: " << uv_strerror(req->result) << std::endl;
|
||||
return;
|
||||
}
|
||||
if (req->result == 0) {
|
||||
// No more bytes left, close the loop
|
||||
uv_fs_t close_req;
|
||||
uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
|
||||
} else if (req->result > 0) {
|
||||
// Start writing after reading some bytes
|
||||
g_iov.len = req->result;
|
||||
uv_fs_write(uv_default_loop(), &write_req, 1, &g_iov, 1, -1, OnWrite);
|
||||
}
|
||||
}
|
||||
|
||||
// Called after the file has been opened
|
||||
// As soon as opening is completed, read the file
|
||||
void OnOpen(uv_fs_t* req) {
|
||||
if (req != &open_req) {
|
||||
std::cerr << "Open error: req != &open_req" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (req->result < 0) {
|
||||
std::cerr << "Open error: " << uv_strerror(static_cast<int>(req->result))
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
// 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
|
||||
// Then close the handle
|
||||
void TimerCallback(uv_timer_t* handle) {
|
||||
int* data = static_cast<int*>(
|
||||
uv_handle_get_data(reinterpret_cast<uv_handle_t*>(handle)));
|
||||
++(*data);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr);
|
||||
}
|
38
oss-internship-2020/libuv/callbacks/callbacks.h
Normal file
38
oss-internship-2020/libuv/callbacks/callbacks.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CALLBACKS_H_
|
||||
#define CALLBACKS_H_
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// idle-basic
|
||||
void IdleCallback(uv_idle_t* handle);
|
||||
|
||||
// uvcat
|
||||
uv_fs_t open_req;
|
||||
uv_fs_t read_req;
|
||||
uv_fs_t write_req;
|
||||
void OnWrite(uv_fs_t* req);
|
||||
void OnRead(uv_fs_t* req);
|
||||
void OnOpen(uv_fs_t* req);
|
||||
|
||||
// test_callback
|
||||
void TimerCallback(uv_timer_t* handle);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // CALLBACKS_H_
|
41
oss-internship-2020/libuv/examples/CMakeLists.txt
Normal file
41
oss-internship-2020/libuv/examples/CMakeLists.txt
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_executable(helloworld
|
||||
helloworld.cc
|
||||
)
|
||||
target_link_libraries(helloworld
|
||||
uv_a
|
||||
uv_sapi
|
||||
sapi::flags
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
add_executable(idle-basic
|
||||
idle-basic.cc
|
||||
)
|
||||
target_link_libraries(idle-basic
|
||||
uv_a
|
||||
uv_sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
add_executable(uvcat
|
||||
uvcat.cc
|
||||
)
|
||||
target_link_libraries(uvcat
|
||||
uv_a
|
||||
uv_sapi
|
||||
sapi::sapi
|
||||
)
|
23
oss-internship-2020/libuv/examples/README.md
Normal file
23
oss-internship-2020/libuv/examples/README.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# 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.
|
||||
|
||||
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.
|
||||
- **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.
|
90
oss-internship-2020/libuv/examples/helloworld.cc
Normal file
90
oss-internship-2020/libuv/examples/helloworld.cc
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "uv_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace {
|
||||
|
||||
class UVSapiHelloworldSandbox : public uv::UVSandbox {
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowSyscalls({__NR_epoll_create1, __NR_eventfd2, __NR_pipe2})
|
||||
.AllowWrite()
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
absl::Status HelloWorld() {
|
||||
// Initialize sandbox2 and sapi
|
||||
UVSapiHelloworldSandbox sandbox;
|
||||
SAPI_RETURN_IF_ERROR(sandbox.Init());
|
||||
uv::UVApi api(&sandbox);
|
||||
|
||||
// Allocate memory for the uv_loop_t object
|
||||
void* loop_voidptr;
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
sandbox.rpc_channel()->Allocate(sizeof(uv_loop_t), &loop_voidptr));
|
||||
sapi::v::RemotePtr loop(loop_voidptr);
|
||||
|
||||
int return_code;
|
||||
|
||||
// Initialize loop
|
||||
SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_loop_init(&loop));
|
||||
if (return_code != 0) {
|
||||
return absl::UnavailableError("uv_loop_init returned error " + return_code);
|
||||
}
|
||||
|
||||
std::cout << "The loop is about to quit" << std::endl;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Close loop
|
||||
SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_loop_close(&loop));
|
||||
if (return_code != 0) {
|
||||
return absl::UnavailableError("uv_loop_close returned error " +
|
||||
return_code);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
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;
|
||||
}
|
112
oss-internship-2020/libuv/examples/idle-basic.cc
Normal file
112
oss-internship-2020/libuv/examples/idle-basic.cc
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "uv_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace {
|
||||
|
||||
class UVSapiIdleBasicSandbox : public uv::UVSandbox {
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowSyscalls({__NR_epoll_create1, __NR_epoll_ctl, __NR_epoll_wait,
|
||||
__NR_eventfd2, __NR_pipe2})
|
||||
.AllowWrite()
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
absl::Status IdleBasic() {
|
||||
// Initialize sandbox2 and sapi
|
||||
UVSapiIdleBasicSandbox sandbox;
|
||||
SAPI_RETURN_IF_ERROR(sandbox.Init());
|
||||
uv::UVApi api(&sandbox);
|
||||
|
||||
// Get remote pointer to the IdleCallback method
|
||||
void* function_ptr;
|
||||
SAPI_RETURN_IF_ERROR(sandbox.rpc_channel()->Symbol("IdleCallback", &function_ptr));
|
||||
sapi::v::RemotePtr idle_callback(function_ptr);
|
||||
|
||||
// Allocate memory for the uv_idle_t object
|
||||
void* idle_voidptr;
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
sandbox.rpc_channel()->Allocate(sizeof(uv_idle_t), &idle_voidptr));
|
||||
sapi::v::RemotePtr idler(idle_voidptr);
|
||||
|
||||
int return_code;
|
||||
|
||||
// Get default loop
|
||||
SAPI_ASSIGN_OR_RETURN(void* loop_voidptr, api.sapi_uv_default_loop());
|
||||
sapi::v::RemotePtr loop(loop_voidptr);
|
||||
|
||||
// Initialize idler
|
||||
SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_idle_init(&loop, &idler));
|
||||
if (return_code != 0) {
|
||||
return absl::UnavailableError("sapi_uv_idle_init returned error " +
|
||||
return_code);
|
||||
}
|
||||
|
||||
// Start idler
|
||||
SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_idle_start(&idler, &idle_callback));
|
||||
if (return_code != 0) {
|
||||
return absl::UnavailableError("sapi_uv_idle_start 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);
|
||||
}
|
||||
|
||||
// Close idler
|
||||
sapi::v::NullPtr null_ptr;
|
||||
SAPI_RETURN_IF_ERROR(api.sapi_uv_close(&idler, &null_ptr));
|
||||
|
||||
// Close loop
|
||||
SAPI_ASSIGN_OR_RETURN(return_code, api.sapi_uv_loop_close(&loop));
|
||||
// UV_EBUSY is accepted because it is the return code of uv_loop_close
|
||||
// in the original example
|
||||
if (return_code != 0 && return_code != UV_EBUSY) {
|
||||
return absl::UnavailableError("uv_loop_close returned error " +
|
||||
return_code);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
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;
|
||||
}
|
111
oss-internship-2020/libuv/examples/uvcat.cc
Normal file
111
oss-internship-2020/libuv/examples/uvcat.cc
Normal file
|
@ -0,0 +1,111 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "uv_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace {
|
||||
|
||||
class UVSapiUVCatSandbox : public uv::UVSandbox {
|
||||
public:
|
||||
UVSapiUVCatSandbox(std::string filename) : filename(filename) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AddFile(filename)
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFork()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowFutexOp(FUTEX_WAIT_PRIVATE)
|
||||
.AllowMmap()
|
||||
.AllowOpen()
|
||||
.AllowSyscalls({__NR_epoll_create1, __NR_epoll_ctl, __NR_epoll_wait,
|
||||
__NR_eventfd2, __NR_pipe2, __NR_prlimit64})
|
||||
.AllowWrite()
|
||||
.BuildOrDie();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
|
||||
if (argc != 2) {
|
||||
LOG(ERROR) << "wrong number of arguments (1 expected)";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (absl::Status status = UVCat(argv[1]); !status.ok()) {
|
||||
LOG(ERROR) << "UVCat failed: " << status.ToString();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
296
oss-internship-2020/libuv/generator/wrapper_generator.py
Normal file
296
oss-internship-2020/libuv/generator/wrapper_generator.py
Normal file
|
@ -0,0 +1,296 @@
|
|||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""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 os
|
||||
import re
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
|
||||
def get_var_type(string: str) -> str:
|
||||
"""Gets the type from an argument variable.
|
||||
|
||||
Args:
|
||||
string: Input variable declaration
|
||||
|
||||
Returns:
|
||||
The type of the argument variable as a string, e.g. "int x" -> "int".
|
||||
"""
|
||||
|
||||
var = string.strip()
|
||||
|
||||
# Unnamed variable
|
||||
if var in ("void", "...") or var[-1] == "*":
|
||||
return var
|
||||
|
||||
return " ".join(var.split(" ")[:-1]).strip()
|
||||
|
||||
|
||||
def get_var_name(string: str) -> str:
|
||||
"""Gets the name from an argument variable.
|
||||
|
||||
Args:
|
||||
string: Input variable declaration
|
||||
|
||||
Returns:
|
||||
The name of the arguments variable as a string, e.g. "int x" -> "x".
|
||||
"""
|
||||
|
||||
var = string.strip()
|
||||
|
||||
# Not an actual variable
|
||||
if var in ("void", "..."):
|
||||
return ""
|
||||
|
||||
# Unnamed variable, use an arbitrary name
|
||||
if var[-1] == "*":
|
||||
return var.split("_")[1]
|
||||
|
||||
return var.split(" ")[-1].strip()
|
||||
|
||||
|
||||
def fix_method_type(string: str) -> str:
|
||||
"""Fixes the method type.
|
||||
|
||||
Args:
|
||||
string: A parameter type declaration
|
||||
|
||||
Returns:
|
||||
A fixed up string replacing pointers to concrete types with pointers to
|
||||
void, e.g. "const int*" -> "const void*".
|
||||
"""
|
||||
|
||||
method_type = string.strip()
|
||||
|
||||
# Const pointer
|
||||
if "*" in method_type and "const" in method_type:
|
||||
return "const void*"
|
||||
|
||||
# Regular pointer
|
||||
if "*" in method_type:
|
||||
return "void*"
|
||||
|
||||
# Not a pointer
|
||||
return method_type
|
||||
|
||||
|
||||
def fix_argument(string: str) -> str:
|
||||
"""Fixes an argument.
|
||||
|
||||
Args:
|
||||
string: An argument type to fix
|
||||
|
||||
Returns:
|
||||
The fixed up argument as a string, e.g. "const int* x" -> "const void* x".
|
||||
"""
|
||||
|
||||
arg_type = get_var_type(string)
|
||||
arg_name = get_var_name(string)
|
||||
|
||||
# Array argument, becomes a pointer
|
||||
if "[" in arg_name:
|
||||
arg_type += "*"
|
||||
arg_name = arg_name.split("[")[0] + arg_name.split("]")[-1]
|
||||
|
||||
# Pointer (in LibUV, types endind in "_cb" or "_func" are pointers)
|
||||
if "*" in arg_type or "_cb" in arg_type or "_func" in arg_type:
|
||||
if "const" in arg_type:
|
||||
return "const void* " + arg_name
|
||||
return "void* " + arg_name
|
||||
|
||||
# Not a pointer
|
||||
return arg_type + " " + arg_name
|
||||
|
||||
|
||||
def fix_call_argument(string: str) -> str:
|
||||
"""Fixes an argument in a call the orignal method.
|
||||
|
||||
Args:
|
||||
string: A method call argument
|
||||
|
||||
Returns:
|
||||
The fixed call argument, e.g. "const int* x" ->
|
||||
"reinterpret_cast<const int*>(x)".
|
||||
"""
|
||||
|
||||
arg_type = get_var_type(string)
|
||||
arg_name = get_var_name(string)
|
||||
|
||||
# Array argument, becomes a pointer
|
||||
if "[" in arg_name:
|
||||
arg_type += "*"
|
||||
arg_name = arg_name.split("[")[0] + arg_name.split("]")[-1]
|
||||
|
||||
# Pointer (in LibUV, types endind in "_cb" or "_func" are pointers)
|
||||
if "*" in arg_type or "_cb" in arg_type or "_func" in arg_type:
|
||||
return "reinterpret_cast<" + arg_type + ">(" + arg_name + ")"
|
||||
|
||||
# Not a pointer
|
||||
return arg_name
|
||||
|
||||
|
||||
def read_file(filename: str) -> str:
|
||||
"""Returns contents of filename as a string.
|
||||
|
||||
Args:
|
||||
filename: The name of the file to read
|
||||
|
||||
Returns:
|
||||
The contents of the file as a string.
|
||||
"""
|
||||
|
||||
file = open(filename, "r")
|
||||
return str(file.read())
|
||||
|
||||
|
||||
def clean_file(text: str) -> str:
|
||||
"""Prepares the file for parsing.
|
||||
|
||||
In particular, removes comments and macros from text
|
||||
Additionally, moves pointer asterisks next to its type
|
||||
|
||||
Args:
|
||||
text: The contents of the text file to prepare
|
||||
|
||||
Returns:
|
||||
The cleaned up file contents.
|
||||
"""
|
||||
|
||||
result = text
|
||||
result = re.sub(r"//.*?\n", "", result, flags=re.S)
|
||||
result = re.sub(r"/\*.*?\*/", "", result, flags=re.S)
|
||||
result = re.sub(r"#.*?\n", "", result, flags=re.S)
|
||||
result = result.replace(" *", "* ")
|
||||
return result
|
||||
|
||||
|
||||
def get_signatures(text: str) -> str:
|
||||
"""Gets the signatures of all the methods in the header.
|
||||
|
||||
Note: This method only works on a certain version of LibUV's header.
|
||||
|
||||
Args:
|
||||
text: The contents of the header file
|
||||
|
||||
Returns:
|
||||
The extracted method signatures.
|
||||
"""
|
||||
|
||||
signatures = [x.split(";")[0].strip() for x in text.split("UV_EXTERN")[1:]]
|
||||
method_types = [
|
||||
" ".join(s.split("(")[0].split(" ")[:-1]).strip() for s in signatures
|
||||
]
|
||||
names = [s.split("(")[0].split(" ")[-1].strip() for s in signatures]
|
||||
arguments = [s.split("(")[1][:-1] for s in signatures]
|
||||
arguments_lists = [[x.strip() for x in a.split(",")] for a in arguments]
|
||||
return zip(method_types, names, arguments_lists)
|
||||
|
||||
|
||||
def append_method(method_type: str, name: str, arguments_list: List[str],
|
||||
header: List[str], source: List[str]) -> None:
|
||||
"""Writes the method to the header and the source list of lines.
|
||||
|
||||
Args:
|
||||
method_type: The return type of the method as a string
|
||||
name: The name of the method
|
||||
arguments_list: A list of method aruments
|
||||
header: A list that receives method wrapper declarations
|
||||
source: A list that receives the declarations of the method wrappers
|
||||
"""
|
||||
|
||||
header.append(
|
||||
fix_method_type(method_type) + " sapi_" + name + "(" +
|
||||
", ".join(map(fix_argument, arguments_list)) + ");")
|
||||
source.append(
|
||||
fix_method_type(method_type) + " sapi_" + name + "(" +
|
||||
", ".join(map(fix_argument, arguments_list)) + ") {\n" + " return " +
|
||||
name + "(" + ", ".join(map(fix_call_argument, arguments_list)) + ");\n" +
|
||||
"}")
|
||||
|
||||
|
||||
def append_text(text: str, file: List[str]) -> None:
|
||||
"""Writes text to file list of lines.
|
||||
|
||||
Useful for additional methods, includes, extern "C"...
|
||||
|
||||
Args:
|
||||
text: The text to append to the file
|
||||
file: A list receiving file lines
|
||||
"""
|
||||
|
||||
file.append(text)
|
||||
|
||||
|
||||
def generate_wrapper() -> None:
|
||||
"""Generates the wrapper."""
|
||||
|
||||
header_file = open(sys.argv[2], "w")
|
||||
source_file = open(sys.argv[3], "w")
|
||||
|
||||
text = read_file(sys.argv[1])
|
||||
text = clean_file(text)
|
||||
signatures = get_signatures(text)
|
||||
|
||||
header = []
|
||||
source = []
|
||||
|
||||
append_text("#include <uv.h>", header)
|
||||
append_text("#include <cstddef>", header)
|
||||
append_text("extern \"C\" {", header)
|
||||
append_text("#include \"" + os.path.abspath(header_file.name) + "\"", source)
|
||||
|
||||
for (method_type, name, arguments_list) in signatures:
|
||||
# These wrapper methods are manually added at the end
|
||||
if name in ("uv_once", "uv_loop_configure"):
|
||||
continue
|
||||
append_method(method_type, name, arguments_list, header, source)
|
||||
|
||||
# Add sapi_uv_once (uv_once uses a differnet kind of callback)
|
||||
append_text("void sapi_uv_once(void* guard, void (*callback)(void));", header)
|
||||
append_text(
|
||||
"void sapi_uv_once(void* guard, void (*callback)(void)) {\n" +
|
||||
" return uv_once(reinterpret_cast<uv_once_t*>(guard)," + "callback);\n" +
|
||||
"}", source)
|
||||
|
||||
# Add sapi_uv_loop_configure (uv_loop_configure is variadic)
|
||||
append_text(
|
||||
"int sapi_uv_loop_configure(void* loop, uv_loop_option option)" + ";",
|
||||
header)
|
||||
append_text(
|
||||
"int sapi_uv_loop_configure(void* loop, uv_loop_option option)" +
|
||||
" {\n return uv_loop_configure(" +
|
||||
"reinterpret_cast<uv_loop_t*>(loop), option);\n" + "}", source)
|
||||
|
||||
# Add sapi_uv_loop_configure_int (uv_loop_configure is variadic)
|
||||
append_text(
|
||||
"int sapi_uv_loop_configure_int(void* loop, " +
|
||||
"uv_loop_option option, int ap);", header)
|
||||
append_text(
|
||||
"int sapi_uv_loop_configure_int(void* loop, " +
|
||||
"uv_loop_option option, int ap) {\n" + " return uv_loop_configure(" +
|
||||
"reinterpret_cast<uv_loop_t*>(loop), option, ap);\n}", source)
|
||||
|
||||
append_text("} // extern \"C\"\n", header)
|
||||
|
||||
header_file.write("\n\n".join(header))
|
||||
source_file.write("\n\n".join(source))
|
||||
|
||||
|
||||
generate_wrapper()
|
1
oss-internship-2020/libuv/libuv
Submodule
1
oss-internship-2020/libuv/libuv
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 2a1b880f5439e074ef4d5c556f626b1044fb6781
|
34
oss-internship-2020/libuv/tests/CMakeLists.txt
Normal file
34
oss-internship-2020/libuv/tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
add_executable(tests
|
||||
test_array.cc
|
||||
test_callback.cc
|
||||
test_error.cc
|
||||
test_loop.cc
|
||||
test_os.cc
|
||||
)
|
||||
|
||||
target_link_libraries(tests
|
||||
gmock
|
||||
gtest
|
||||
gtest_main
|
||||
uv_a
|
||||
uv_sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
gtest_discover_tests(tests)
|
71
oss-internship-2020/libuv/tests/test_array.cc
Normal file
71
oss-internship-2020/libuv/tests/test_array.cc
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
#include "uv_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace {
|
||||
|
||||
class UVTestArraySapiSandbox : public uv::UVSandbox {
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowOpen()
|
||||
.AllowSyscall(__NR_sysinfo)
|
||||
.AllowWrite()
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
class UVTestArray : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
sandbox_ = std::make_unique<UVTestArraySapiSandbox>();
|
||||
ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
|
||||
api_ = std::make_unique<uv::UVApi>(sandbox_.get());
|
||||
}
|
||||
|
||||
std::unique_ptr<UVTestArraySapiSandbox> sandbox_;
|
||||
std::unique_ptr<uv::UVApi> api_;
|
||||
};
|
||||
|
||||
TEST_F(UVTestArray, LoadAvg) {
|
||||
double avg_buf[] = {-1, -1, -1};
|
||||
sapi::v::Array<double> avg(avg_buf, 3);
|
||||
|
||||
// Check that loadavg is as initialized before call
|
||||
ASSERT_EQ(avg_buf[0], -1);
|
||||
ASSERT_EQ(avg_buf[1], -1);
|
||||
ASSERT_EQ(avg_buf[2], -1);
|
||||
|
||||
// Get loadavg
|
||||
ASSERT_THAT(api_->sapi_uv_loadavg(avg.PtrBoth()), sapi::IsOk());
|
||||
|
||||
// Check that loadavg values are positive
|
||||
ASSERT_GE(avg_buf[0], 0);
|
||||
ASSERT_GE(avg_buf[1], 0);
|
||||
ASSERT_GE(avg_buf[2], 0);
|
||||
}
|
||||
|
||||
} // namespace
|
142
oss-internship-2020/libuv/tests/test_callback.cc
Normal file
142
oss-internship-2020/libuv/tests/test_callback.cc
Normal file
|
@ -0,0 +1,142 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
#include "uv_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace {
|
||||
|
||||
class UVTestCallbackSapiSandbox : public uv::UVSandbox {
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.DangerDefaultAllowAll()
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowSyscalls({__NR_epoll_create1, __NR_eventfd2, __NR_pipe2})
|
||||
.AllowWrite()
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
class UVTestCallback : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
sandbox_ = std::make_unique<UVTestCallbackSapiSandbox>();
|
||||
ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
|
||||
api_ = std::make_unique<uv::UVApi>(sandbox_.get());
|
||||
}
|
||||
|
||||
// Check sapi_uv_timer_init
|
||||
void UVTimerInit(sapi::v::Ptr* loop, sapi::v::Ptr* timer) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int error_code, api_->sapi_uv_timer_init(loop, timer));
|
||||
ASSERT_EQ(error_code, 0);
|
||||
}
|
||||
|
||||
// Check sapi_uv_timer_start
|
||||
// (actual time is ignored because timeout and repeat are 0)
|
||||
void UVTimerStart(sapi::v::Ptr* timer) {
|
||||
// Get the TimerCallback callback from the sandbox
|
||||
void* timer_cb_voidptr;
|
||||
ASSERT_THAT(
|
||||
sandbox_->rpc_channel()->Symbol("TimerCallback", &timer_cb_voidptr),
|
||||
sapi::IsOk());
|
||||
sapi::v::RemotePtr timer_cb(timer_cb_voidptr);
|
||||
|
||||
// Set the timer's callback, timeout and repeat
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int error_code,
|
||||
api_->sapi_uv_timer_start(timer, &timer_cb, 0, 0));
|
||||
ASSERT_EQ(error_code, 0);
|
||||
}
|
||||
|
||||
// Check sapi_uv_run
|
||||
void UVRun(sapi::v::Ptr* loop) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int error_code,
|
||||
api_->sapi_uv_run(loop, UV_RUN_DEFAULT));
|
||||
ASSERT_EQ(error_code, 0);
|
||||
}
|
||||
|
||||
// Check sapi_uv_loop_close
|
||||
void UVLoopClose(sapi::v::Ptr* loop) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int error_code, api_->sapi_uv_loop_close(loop));
|
||||
ASSERT_EQ(error_code, 0);
|
||||
}
|
||||
|
||||
// Check sapi_uv_default_loop, set loop to default loop
|
||||
void UVDefaultLoop(sapi::v::Ptr* loop) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(void* loop_voidptr, api_->sapi_uv_default_loop());
|
||||
loop->SetRemote(loop_voidptr);
|
||||
}
|
||||
|
||||
std::unique_ptr<UVTestCallbackSapiSandbox> sandbox_;
|
||||
std::unique_ptr<uv::UVApi> api_;
|
||||
|
||||
static constexpr int kData = 1729;
|
||||
};
|
||||
|
||||
TEST_F(UVTestCallback, TimerCallback) {
|
||||
// Initialize loop
|
||||
sapi::v::RemotePtr loop(nullptr);
|
||||
|
||||
// Allocate memory for timer
|
||||
void* timer_voidptr;
|
||||
ASSERT_THAT(
|
||||
sandbox_->rpc_channel()->Allocate(sizeof(uv_timer_t), &timer_voidptr),
|
||||
sapi::IsOk());
|
||||
sapi::v::RemotePtr timer(timer_voidptr);
|
||||
|
||||
// Initialize timer and add it to default loop
|
||||
UVDefaultLoop(&loop);
|
||||
UVTimerInit(loop.PtrNone(), timer.PtrBoth());
|
||||
|
||||
// Set timer data to kData
|
||||
sapi::v::Int data(kData);
|
||||
void* data_voidptr;
|
||||
ASSERT_THAT(sandbox_->rpc_channel()->Allocate(sizeof(int), &data_voidptr),
|
||||
sapi::IsOk());
|
||||
data.SetRemote(data_voidptr);
|
||||
ASSERT_THAT(api_->sapi_uv_handle_set_data(timer.PtrBoth(), data.PtrBefore()),
|
||||
sapi::IsOk());
|
||||
|
||||
// Start the timer
|
||||
UVTimerStart(timer.PtrBoth());
|
||||
|
||||
// Check that data has not changed (because the loop is not running yet)
|
||||
// This is done by resetting the local value and then getting the remote one
|
||||
data.SetValue(0);
|
||||
ASSERT_THAT(sandbox_->TransferFromSandboxee(&data), sapi::IsOk());
|
||||
ASSERT_EQ(data.GetValue(), kData);
|
||||
|
||||
// Run the loop
|
||||
UVDefaultLoop(&loop);
|
||||
UVRun(loop.PtrNone());
|
||||
|
||||
// Check that data has changed (and therefore callback was called correctly)
|
||||
ASSERT_THAT(sandbox_->TransferFromSandboxee(&data), sapi::IsOk());
|
||||
ASSERT_EQ(data.GetValue(), kData + 1);
|
||||
|
||||
// Close the loop
|
||||
UVDefaultLoop(&loop);
|
||||
UVLoopClose(loop.PtrNone());
|
||||
}
|
||||
|
||||
} // namespace
|
94
oss-internship-2020/libuv/tests/test_error.cc
Normal file
94
oss-internship-2020/libuv/tests/test_error.cc
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
#include "uv_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace {
|
||||
|
||||
class UVTestErrorSapiSandbox : public uv::UVSandbox {
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowWrite()
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
class UVTestError : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
sandbox_ = std::make_unique<UVTestErrorSapiSandbox>();
|
||||
ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
|
||||
api_ = std::make_unique<uv::UVApi>(sandbox_.get());
|
||||
}
|
||||
|
||||
// Check sapi_uv_strerror on error
|
||||
void UVStrerror(int error) {
|
||||
// Call sapi_uv_strerror
|
||||
absl::StatusOr<void*> error_message_ptr = api_->sapi_uv_strerror(error);
|
||||
ASSERT_THAT(error_message_ptr, sapi::IsOk());
|
||||
|
||||
// Get error message from the sandboxee
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
std::string error_message,
|
||||
sandbox_->GetCString(sapi::v::RemotePtr{error_message_ptr.value()}));
|
||||
|
||||
// Check that it is equal to expected error message
|
||||
ASSERT_EQ(error_message, std::string{uv_strerror(error)});
|
||||
}
|
||||
|
||||
// Check sapi_uv_translate_sys_error on error
|
||||
void UVTranslateSysError(int error) {
|
||||
// Call sapi_uv_translate_sys_error and get error code
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int error_code,
|
||||
api_->sapi_uv_translate_sys_error(error));
|
||||
|
||||
// Check that it is equal to expected error code
|
||||
ASSERT_EQ(error_code, uv_translate_sys_error(error));
|
||||
}
|
||||
|
||||
std::unique_ptr<UVTestErrorSapiSandbox> sandbox_;
|
||||
std::unique_ptr<uv::UVApi> api_;
|
||||
};
|
||||
|
||||
TEST_F(UVTestError, ErrorMessage) {
|
||||
// Test sapi_uv_strerror method
|
||||
UVStrerror(0);
|
||||
UVStrerror(UV_EINVAL);
|
||||
UVStrerror(1337);
|
||||
UVStrerror(-1337);
|
||||
}
|
||||
|
||||
TEST_F(UVTestError, SystemError) {
|
||||
// Test sapi_uv_translate_sys_error method
|
||||
UVTranslateSysError(EPERM);
|
||||
UVTranslateSysError(EPIPE);
|
||||
UVTranslateSysError(EINVAL);
|
||||
UVTranslateSysError(UV_EINVAL);
|
||||
UVTranslateSysError(UV_ERANGE);
|
||||
UVTranslateSysError(UV_EACCES);
|
||||
UVTranslateSysError(0);
|
||||
}
|
||||
|
||||
} // namespace
|
106
oss-internship-2020/libuv/tests/test_loop.cc
Normal file
106
oss-internship-2020/libuv/tests/test_loop.cc
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
#include "uv_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace {
|
||||
|
||||
class UVTestLoopSapiSandbox : public uv::UVSandbox {
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowSyscalls({__NR_epoll_create1, __NR_eventfd2, __NR_pipe2})
|
||||
.AllowWrite()
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
class UVTestLoop : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
sandbox_ = std::make_unique<UVTestLoopSapiSandbox>();
|
||||
ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
|
||||
api_ = std::make_unique<uv::UVApi>(sandbox_.get());
|
||||
}
|
||||
|
||||
// Check sapi_uv_loop_init
|
||||
void UVLoopInit(sapi::v::Ptr* loop) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int error_code, api_->sapi_uv_loop_init(loop));
|
||||
ASSERT_EQ(error_code, 0);
|
||||
}
|
||||
|
||||
// Check sapi_uv_run
|
||||
void UVRun(sapi::v::Ptr* loop) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int error_code,
|
||||
api_->sapi_uv_run(loop, UV_RUN_DEFAULT));
|
||||
ASSERT_EQ(error_code, 0);
|
||||
}
|
||||
|
||||
// Check sapi_uv_loop_close
|
||||
void UVLoopClose(sapi::v::Ptr* loop) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int error_code, api_->sapi_uv_loop_close(loop));
|
||||
ASSERT_EQ(error_code, 0);
|
||||
}
|
||||
|
||||
// Check sapi_uv_default_loop, set loop to default loop
|
||||
void UVDefaultLoop(sapi::v::Ptr* loop) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(void* loop_voidptr, api_->sapi_uv_default_loop());
|
||||
loop->SetRemote(loop_voidptr);
|
||||
}
|
||||
|
||||
std::unique_ptr<UVTestLoopSapiSandbox> sandbox_;
|
||||
std::unique_ptr<uv::UVApi> api_;
|
||||
};
|
||||
|
||||
TEST_F(UVTestLoop, InitLoop) {
|
||||
// Allocate memory for loop
|
||||
void* loop_voidptr;
|
||||
ASSERT_THAT(
|
||||
sandbox_->rpc_channel()->Allocate(sizeof(uv_loop_t), &loop_voidptr),
|
||||
sapi::IsOk());
|
||||
sapi::v::RemotePtr loop(loop_voidptr);
|
||||
|
||||
// Initialize, run and close the manually initialized loop
|
||||
UVLoopInit(loop.PtrBoth());
|
||||
UVRun(loop.PtrNone());
|
||||
UVLoopClose(loop.PtrNone());
|
||||
|
||||
// Free loop memory
|
||||
ASSERT_THAT(sandbox_->rpc_channel()->Free(loop_voidptr), sapi::IsOk());
|
||||
}
|
||||
|
||||
TEST_F(UVTestLoop, DefaultLoop) {
|
||||
sapi::v::RemotePtr loop(nullptr);
|
||||
|
||||
// Run the default loop
|
||||
UVDefaultLoop(&loop);
|
||||
UVRun(loop.PtrNone());
|
||||
|
||||
// Close the default loop
|
||||
UVDefaultLoop(&loop);
|
||||
UVLoopClose(loop.PtrNone());
|
||||
}
|
||||
|
||||
} // namespace
|
137
oss-internship-2020/libuv/tests/test_os.cc
Normal file
137
oss-internship-2020/libuv/tests/test_os.cc
Normal file
|
@ -0,0 +1,137 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <syscall.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
#include "uv_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace {
|
||||
|
||||
class UVTestOSSapiSandbox : public uv::UVSandbox {
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowGetIDs()
|
||||
.AllowMmap()
|
||||
.AllowOpen()
|
||||
.AllowWrite()
|
||||
.AllowSyscalls({__NR_connect, __NR_socket})
|
||||
.DisableNamespaces()
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
class UVTestOS : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
sandbox_ = std::make_unique<UVTestOSSapiSandbox>();
|
||||
ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
|
||||
api_ = std::make_unique<uv::UVApi>(sandbox_.get());
|
||||
}
|
||||
|
||||
std::unique_ptr<UVTestOSSapiSandbox> sandbox_;
|
||||
std::unique_ptr<uv::UVApi> api_;
|
||||
|
||||
static constexpr size_t kBigBufLen = 4096;
|
||||
static constexpr size_t kSmallBufLen = 1;
|
||||
};
|
||||
|
||||
TEST_F(UVTestOS, HomeDirBig) {
|
||||
// Get expected home directory
|
||||
char expected_homedir[kBigBufLen];
|
||||
size_t len = sizeof(expected_homedir);
|
||||
ASSERT_GE(uv_os_homedir(expected_homedir, &len), 0);
|
||||
|
||||
// Get home directory from the sandbox
|
||||
sapi::v::Array<char> uv_homedir(kBigBufLen);
|
||||
uv_homedir[0] = '\0';
|
||||
sapi::v::IntBase<size_t> uv_homedir_len(kBigBufLen);
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int error_code,
|
||||
api_->sapi_uv_os_homedir(uv_homedir.PtrBoth(), uv_homedir_len.PtrBoth()));
|
||||
ASSERT_GE(error_code, 0);
|
||||
|
||||
// Test home directory is as expected
|
||||
ASSERT_EQ(std::string{uv_homedir.GetData()}, std::string{expected_homedir});
|
||||
}
|
||||
|
||||
TEST_F(UVTestOS, HomeDirSmall) {
|
||||
// Try getting expected home directory, error because array is too small
|
||||
char expected_homedir[kSmallBufLen];
|
||||
size_t len = sizeof(expected_homedir);
|
||||
int expected_error_code = uv_os_homedir(expected_homedir, &len);
|
||||
ASSERT_NE(expected_error_code, 0);
|
||||
|
||||
// Try getting home directory from sandbox, error because array is too small
|
||||
sapi::v::Array<char> uv_homedir(kSmallBufLen);
|
||||
uv_homedir[0] = '\0';
|
||||
sapi::v::IntBase<size_t> uv_homedir_len(kSmallBufLen);
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int error_code,
|
||||
api_->sapi_uv_os_homedir(uv_homedir.PtrBoth(), uv_homedir_len.PtrBoth()));
|
||||
ASSERT_NE(error_code, 0);
|
||||
|
||||
// Test error code is as expected
|
||||
ASSERT_EQ(error_code, expected_error_code);
|
||||
}
|
||||
|
||||
TEST_F(UVTestOS, TmpDirBig) {
|
||||
// Get expected tmp directory
|
||||
char expected_tmpdir[kBigBufLen];
|
||||
size_t len = sizeof(expected_tmpdir);
|
||||
ASSERT_GE(uv_os_tmpdir(expected_tmpdir, &len), 0);
|
||||
|
||||
// Get tmp directory from the sandbox
|
||||
sapi::v::Array<char> uv_tmpdir(kBigBufLen);
|
||||
uv_tmpdir[0] = '\0';
|
||||
sapi::v::IntBase<size_t> uv_tmpdir_len(kBigBufLen);
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int error_code,
|
||||
api_->sapi_uv_os_tmpdir(uv_tmpdir.PtrBoth(), uv_tmpdir_len.PtrBoth()));
|
||||
ASSERT_GE(error_code, 0);
|
||||
|
||||
// Test tmp directory is as expected
|
||||
ASSERT_EQ(std::string{uv_tmpdir.GetData()}, std::string{expected_tmpdir});
|
||||
}
|
||||
|
||||
TEST_F(UVTestOS, TmpDirSmall) {
|
||||
// Try getting expected tmp directory, error because array is too small
|
||||
char expected_tmpdir[kSmallBufLen];
|
||||
size_t len = sizeof(expected_tmpdir);
|
||||
int expected_error_code = uv_os_tmpdir(expected_tmpdir, &len);
|
||||
ASSERT_NE(expected_error_code, 0);
|
||||
|
||||
// Try getting tmp directory from sandbox, error because array is too small
|
||||
sapi::v::Array<char> uv_tmpdir(kSmallBufLen);
|
||||
uv_tmpdir[0] = '\0';
|
||||
sapi::v::IntBase<size_t> uv_tmpdir_len(kSmallBufLen);
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int error_code,
|
||||
api_->sapi_uv_os_tmpdir(uv_tmpdir.PtrBoth(), uv_tmpdir_len.PtrBoth()));
|
||||
ASSERT_NE(error_code, 0);
|
||||
|
||||
// Test error code is as expected
|
||||
ASSERT_EQ(error_code, expected_error_code);
|
||||
}
|
||||
|
||||
} // namespace
|
Loading…
Reference in New Issue
Block a user