1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <array>
18 #include <cstdint>
19 #include <memory>
20 
21 #include <gtest/gtest.h>
22 
23 #include "netdutils/Handle.h"
24 #include "netdutils/Math.h"
25 #include "netdutils/MockSyscalls.h"
26 #include "netdutils/Netfilter.h"
27 #include "netdutils/Netlink.h"
28 #include "netdutils/Slice.h"
29 #include "netdutils/Status.h"
30 #include "netdutils/StatusOr.h"
31 #include "netdutils/Syscalls.h"
32 
33 using testing::_;
34 using testing::ByMove;
35 using testing::Invoke;
36 using testing::Return;
37 using testing::StrictMock;
38 
39 namespace android {
40 namespace netdutils {
41 
42 class SyscallsTest : public testing::Test {
43   protected:
44     StrictMock<ScopedMockSyscalls> mSyscalls;
45 };
46 
TEST(syscalls,scopedMock)47 TEST(syscalls, scopedMock) {
48     auto& old = sSyscalls.get();
49     {
50         StrictMock<ScopedMockSyscalls> s;
51         EXPECT_EQ(&s, &sSyscalls.get());
52     }
53     EXPECT_EQ(&old, &sSyscalls.get());
54 }
55 
TEST_F(SyscallsTest,open)56 TEST_F(SyscallsTest, open) {
57     const char kPath[] = "/test/path/please/ignore";
58     constexpr Fd kFd(40);
59     constexpr int kFlags = 883;
60     constexpr mode_t kMode = 37373;
61     const auto& sys = sSyscalls.get();
62     EXPECT_CALL(mSyscalls, open(kPath, kFlags, kMode)).WillOnce(Return(ByMove(UniqueFd(kFd))));
63     EXPECT_CALL(mSyscalls, close(kFd)).WillOnce(Return(status::ok));
64     auto result = sys.open(kPath, kFlags, kMode);
65     EXPECT_EQ(status::ok, result.status());
66     EXPECT_EQ(kFd, result.value());
67 }
68 
TEST_F(SyscallsTest,getsockname)69 TEST_F(SyscallsTest, getsockname) {
70     constexpr Fd kFd(40);
71     sockaddr_nl expected = {};
72     auto& sys = sSyscalls.get();
73 
74     // Success
75     EXPECT_CALL(mSyscalls, getsockname(kFd, _, _))
76         .WillOnce(Invoke([expected](Fd, sockaddr* addr, socklen_t* addrlen) {
77             memcpy(addr, &expected, sizeof(expected));
78             EXPECT_EQ(*addrlen, static_cast<socklen_t>(sizeof(expected)));
79             return status::ok;
80         }));
81     const auto result = sys.getsockname<sockaddr_nl>(kFd);
82     EXPECT_TRUE(isOk(result));
83     EXPECT_EQ(expected, result.value());
84 
85     // Failure
86     const Status kError = statusFromErrno(EINVAL, "test");
87     EXPECT_CALL(mSyscalls, getsockname(kFd, _, _)).WillOnce(Return(kError));
88     EXPECT_EQ(kError, sys.getsockname<sockaddr_nl>(kFd).status());
89 }
90 
TEST_F(SyscallsTest,setsockopt)91 TEST_F(SyscallsTest, setsockopt) {
92     constexpr Fd kFd(40);
93     constexpr int kLevel = 50;
94     constexpr int kOptname = 70;
95     sockaddr_nl expected = {};
96     auto& sys = sSyscalls.get();
97 
98     // Success
99     EXPECT_CALL(mSyscalls, setsockopt(kFd, kLevel, kOptname, &expected, sizeof(expected)))
100         .WillOnce(Return(status::ok));
101     EXPECT_EQ(status::ok, sys.setsockopt(kFd, kLevel, kOptname, expected));
102 
103     // Failure
104     const Status kError = statusFromErrno(EINVAL, "test");
105     EXPECT_CALL(mSyscalls, setsockopt(kFd, kLevel, kOptname, &expected, sizeof(expected)))
106         .WillOnce(Return(kError));
107     EXPECT_EQ(kError, sys.setsockopt(kFd, kLevel, kOptname, expected));
108 }
109 
TEST_F(SyscallsTest,getsockopt)110 TEST_F(SyscallsTest, getsockopt) {
111     constexpr Fd kFd(40);
112     constexpr int kLevel = 50;
113     constexpr int kOptname = 70;
114     sockaddr_nl expected = {};
115     socklen_t optLen = 0;
116     auto& sys = sSyscalls.get();
117 
118     // Success
119     EXPECT_CALL(mSyscalls, getsockopt(kFd, kLevel, kOptname, &expected, &optLen))
120         .WillOnce(Return(status::ok));
121     EXPECT_EQ(status::ok, sys.getsockopt(kFd, kLevel, kOptname, &expected, &optLen));
122 
123     // Failure
124     const Status kError = statusFromErrno(EINVAL, "test");
125     EXPECT_CALL(mSyscalls, getsockopt(kFd, kLevel, kOptname, &expected, &optLen))
126         .WillOnce(Return(kError));
127     EXPECT_EQ(kError, sys.getsockopt(kFd, kLevel, kOptname, &expected, &optLen));
128 }
129 
TEST_F(SyscallsTest,bind)130 TEST_F(SyscallsTest, bind) {
131     constexpr Fd kFd(40);
132     sockaddr_nl expected = {};
133     auto& sys = sSyscalls.get();
134 
135     // Success
136     EXPECT_CALL(mSyscalls, bind(kFd, asSockaddrPtr(&expected), sizeof(expected)))
137         .WillOnce(Return(status::ok));
138     EXPECT_EQ(status::ok, sys.bind(kFd, expected));
139 
140     // Failure
141     const Status kError = statusFromErrno(EINVAL, "test");
142     EXPECT_CALL(mSyscalls, bind(kFd, asSockaddrPtr(&expected), sizeof(expected)))
143         .WillOnce(Return(kError));
144     EXPECT_EQ(kError, sys.bind(kFd, expected));
145 }
146 
TEST_F(SyscallsTest,connect)147 TEST_F(SyscallsTest, connect) {
148     constexpr Fd kFd(40);
149     sockaddr_nl expected = {};
150     auto& sys = sSyscalls.get();
151 
152     // Success
153     EXPECT_CALL(mSyscalls, connect(kFd, asSockaddrPtr(&expected), sizeof(expected)))
154         .WillOnce(Return(status::ok));
155     EXPECT_EQ(status::ok, sys.connect(kFd, expected));
156 
157     // Failure
158     const Status kError = statusFromErrno(EINVAL, "test");
159     EXPECT_CALL(mSyscalls, connect(kFd, asSockaddrPtr(&expected), sizeof(expected)))
160         .WillOnce(Return(kError));
161     EXPECT_EQ(kError, sys.connect(kFd, expected));
162 }
163 
TEST_F(SyscallsTest,sendto)164 TEST_F(SyscallsTest, sendto) {
165     constexpr Fd kFd(40);
166     constexpr int kFlags = 0;
167     std::array<char, 10> payload;
168     const auto slice = makeSlice(payload);
169     sockaddr_nl expected = {};
170     auto& sys = sSyscalls.get();
171 
172     // Success
173     EXPECT_CALL(mSyscalls, sendto(kFd, slice, kFlags, asSockaddrPtr(&expected), sizeof(expected)))
174         .WillOnce(Return(slice.size()));
175     EXPECT_EQ(status::ok, sys.sendto(kFd, slice, kFlags, expected));
176 }
177 
TEST_F(SyscallsTest,recvfrom)178 TEST_F(SyscallsTest, recvfrom) {
179     constexpr Fd kFd(40);
180     constexpr int kFlags = 0;
181     std::array<char, 10> payload;
182     const auto dst = makeSlice(payload);
183     const auto used = take(dst, 8);
184     sockaddr_nl expected = {};
185     auto& sys = sSyscalls.get();
186 
187     // Success
188     EXPECT_CALL(mSyscalls, recvfrom(kFd, dst, kFlags, _, _))
189             .WillOnce(Invoke(
190                     [expected, used](Fd, const Slice, int, sockaddr* src, socklen_t* srclen) {
191                         *srclen = sizeof(expected);
192                         memcpy(src, &expected, *srclen);
193                         return used;
194                     }));
195     auto result = sys.recvfrom<sockaddr_nl>(kFd, dst, kFlags);
196     EXPECT_EQ(status::ok, result.status());
197     EXPECT_EQ(used, result.value().first);
198     EXPECT_EQ(expected, result.value().second);
199 }
200 
201 }  // namespace netdutils
202 }  // namespace android
203