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