1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <linux/futex.h>
16 #include <syscall.h>
17 #include <uv.h>
18
19 #include "gtest/gtest.h"
20 #include "absl/flags/flag.h"
21 #include "sandboxed_api/util/status_matchers.h"
22 #include "uv_sapi.sapi.h" // NOLINT(build/include)
23
24 namespace {
25
26 class UVTestLoopSapiSandbox : public uv::UVSandbox {
27 private:
ModifyPolicy(sandbox2::PolicyBuilder *)28 std::unique_ptr<sandbox2::Policy> ModifyPolicy(
29 sandbox2::PolicyBuilder*) override {
30 return sandbox2::PolicyBuilder()
31 .AllowDynamicStartup()
32 .AllowExit()
33 .AllowFutexOp(FUTEX_WAKE_PRIVATE)
34 .AllowSyscalls({__NR_epoll_create1, __NR_eventfd2, __NR_pipe2})
35 .AllowWrite()
36 .BuildOrDie();
37 }
38 };
39
40 class UVTestLoop : public ::testing::Test {
41 protected:
SetUp()42 void SetUp() override {
43 sandbox_ = std::make_unique<UVTestLoopSapiSandbox>();
44 ASSERT_THAT(sandbox_->Init(), sapi::IsOk());
45 api_ = std::make_unique<uv::UVApi>(sandbox_.get());
46 }
47
48 // Check sapi_uv_loop_init
UVLoopInit(sapi::v::Ptr * loop)49 void UVLoopInit(sapi::v::Ptr* loop) {
50 SAPI_ASSERT_OK_AND_ASSIGN(int error_code, api_->sapi_uv_loop_init(loop));
51 ASSERT_EQ(error_code, 0);
52 }
53
54 // Check sapi_uv_run
UVRun(sapi::v::Ptr * loop)55 void UVRun(sapi::v::Ptr* loop) {
56 SAPI_ASSERT_OK_AND_ASSIGN(int error_code,
57 api_->sapi_uv_run(loop, UV_RUN_DEFAULT));
58 ASSERT_EQ(error_code, 0);
59 }
60
61 // Check sapi_uv_loop_close
UVLoopClose(sapi::v::Ptr * loop)62 void UVLoopClose(sapi::v::Ptr* loop) {
63 SAPI_ASSERT_OK_AND_ASSIGN(int error_code, api_->sapi_uv_loop_close(loop));
64 ASSERT_EQ(error_code, 0);
65 }
66
67 // Check sapi_uv_default_loop, set loop to default loop
UVDefaultLoop(sapi::v::Ptr * loop)68 void UVDefaultLoop(sapi::v::Ptr* loop) {
69 SAPI_ASSERT_OK_AND_ASSIGN(void* loop_voidptr, api_->sapi_uv_default_loop());
70 loop->SetRemote(loop_voidptr);
71 }
72
73 std::unique_ptr<UVTestLoopSapiSandbox> sandbox_;
74 std::unique_ptr<uv::UVApi> api_;
75 };
76
TEST_F(UVTestLoop,InitLoop)77 TEST_F(UVTestLoop, InitLoop) {
78 // Allocate memory for loop
79 void* loop_voidptr;
80 ASSERT_THAT(
81 sandbox_->rpc_channel()->Allocate(sizeof(uv_loop_t), &loop_voidptr),
82 sapi::IsOk());
83 sapi::v::RemotePtr loop(loop_voidptr);
84
85 // Initialize, run and close the manually initialized loop
86 UVLoopInit(loop.PtrBoth());
87 UVRun(loop.PtrNone());
88 UVLoopClose(loop.PtrNone());
89
90 // Free loop memory
91 ASSERT_THAT(sandbox_->rpc_channel()->Free(loop_voidptr), sapi::IsOk());
92 }
93
TEST_F(UVTestLoop,DefaultLoop)94 TEST_F(UVTestLoop, DefaultLoop) {
95 sapi::v::RemotePtr loop(nullptr);
96
97 // Run the default loop
98 UVDefaultLoop(&loop);
99 UVRun(loop.PtrNone());
100
101 // Close the default loop
102 UVDefaultLoop(&loop);
103 UVLoopClose(loop.PtrNone());
104 }
105
106 } // namespace
107