• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::ByMove;
34 using testing::DoAll;
35 using testing::Invoke;
36 using testing::Mock;
37 using testing::Return;
38 using testing::StrictMock;
39 using testing::_;
40 
41 namespace android {
42 namespace netdutils {
43 
44 class SyscallsTest : public testing::Test {
45   protected:
46     StrictMock<ScopedMockSyscalls> mSyscalls;
47 };
48 
TEST(syscalls,scopedMock)49 TEST(syscalls, scopedMock) {
50     auto& old = sSyscalls.get();
51     {
52         StrictMock<ScopedMockSyscalls> s;
53         EXPECT_EQ(&s, &sSyscalls.get());
54     }
55     EXPECT_EQ(&old, &sSyscalls.get());
56 }
57 
TEST_F(SyscallsTest,open)58 TEST_F(SyscallsTest, open) {
59     const char kPath[] = "/test/path/please/ignore";
60     constexpr Fd kFd(40);
61     constexpr int kFlags = 883;
62     constexpr mode_t kMode = 37373;
63     const auto& sys = sSyscalls.get();
64     EXPECT_CALL(mSyscalls, open(kPath, kFlags, kMode)).WillOnce(Return(ByMove(UniqueFd(kFd))));
65     auto result = sys.open(kPath, kFlags, kMode);
66     EXPECT_EQ(status::ok, result.status());
67     EXPECT_EQ(kFd, result.value());
68 }
69 
TEST_F(SyscallsTest,getsockname)70 TEST_F(SyscallsTest, getsockname) {
71     constexpr Fd kFd(40);
72     sockaddr_nl expected = {};
73     auto& sys = sSyscalls.get();
74 
75     // Success
76     EXPECT_CALL(mSyscalls, getsockname(kFd, _, _))
77         .WillOnce(Invoke([expected](Fd, sockaddr* addr, socklen_t* addrlen) {
78             memcpy(addr, &expected, sizeof(expected));
79             EXPECT_EQ(*addrlen, static_cast<socklen_t>(sizeof(expected)));
80             return status::ok;
81         }));
82     const auto result = sys.getsockname<sockaddr_nl>(kFd);
83     EXPECT_TRUE(isOk(result));
84     EXPECT_EQ(expected, result.value());
85 
86     // Failure
87     const Status kError = statusFromErrno(EINVAL, "test");
88     EXPECT_CALL(mSyscalls, getsockname(kFd, _, _)).WillOnce(Return(kError));
89     EXPECT_EQ(kError, sys.getsockname<sockaddr_nl>(kFd).status());
90 }
91 
TEST_F(SyscallsTest,setsockopt)92 TEST_F(SyscallsTest, setsockopt) {
93     constexpr Fd kFd(40);
94     constexpr int kLevel = 50;
95     constexpr int kOptname = 70;
96     sockaddr_nl expected = {};
97     auto& sys = sSyscalls.get();
98 
99     // Success
100     EXPECT_CALL(mSyscalls, setsockopt(kFd, kLevel, kOptname, &expected, sizeof(expected)))
101         .WillOnce(Return(status::ok));
102     EXPECT_EQ(status::ok, sys.setsockopt(kFd, kLevel, kOptname, expected));
103 
104     // Failure
105     const Status kError = statusFromErrno(EINVAL, "test");
106     EXPECT_CALL(mSyscalls, setsockopt(kFd, kLevel, kOptname, &expected, sizeof(expected)))
107         .WillOnce(Return(kError));
108     EXPECT_EQ(kError, sys.setsockopt(kFd, kLevel, kOptname, expected));
109 }
110 
TEST_F(SyscallsTest,getsockopt)111 TEST_F(SyscallsTest, getsockopt) {
112     constexpr Fd kFd(40);
113     constexpr int kLevel = 50;
114     constexpr int kOptname = 70;
115     sockaddr_nl expected = {};
116     socklen_t optLen = 0;
117     auto& sys = sSyscalls.get();
118 
119     // Success
120     EXPECT_CALL(mSyscalls, getsockopt(kFd, kLevel, kOptname, &expected, &optLen))
121         .WillOnce(Return(status::ok));
122     EXPECT_EQ(status::ok, sys.getsockopt(kFd, kLevel, kOptname, &expected, &optLen));
123 
124     // Failure
125     const Status kError = statusFromErrno(EINVAL, "test");
126     EXPECT_CALL(mSyscalls, getsockopt(kFd, kLevel, kOptname, &expected, &optLen))
127         .WillOnce(Return(kError));
128     EXPECT_EQ(kError, sys.getsockopt(kFd, kLevel, kOptname, &expected, &optLen));
129 }
130 
TEST_F(SyscallsTest,bind)131 TEST_F(SyscallsTest, bind) {
132     constexpr Fd kFd(40);
133     sockaddr_nl expected = {};
134     auto& sys = sSyscalls.get();
135 
136     // Success
137     EXPECT_CALL(mSyscalls, bind(kFd, asSockaddrPtr(&expected), sizeof(expected)))
138         .WillOnce(Return(status::ok));
139     EXPECT_EQ(status::ok, sys.bind(kFd, expected));
140 
141     // Failure
142     const Status kError = statusFromErrno(EINVAL, "test");
143     EXPECT_CALL(mSyscalls, bind(kFd, asSockaddrPtr(&expected), sizeof(expected)))
144         .WillOnce(Return(kError));
145     EXPECT_EQ(kError, sys.bind(kFd, expected));
146 }
147 
TEST_F(SyscallsTest,connect)148 TEST_F(SyscallsTest, connect) {
149     constexpr Fd kFd(40);
150     sockaddr_nl expected = {};
151     auto& sys = sSyscalls.get();
152 
153     // Success
154     EXPECT_CALL(mSyscalls, connect(kFd, asSockaddrPtr(&expected), sizeof(expected)))
155         .WillOnce(Return(status::ok));
156     EXPECT_EQ(status::ok, sys.connect(kFd, expected));
157 
158     // Failure
159     const Status kError = statusFromErrno(EINVAL, "test");
160     EXPECT_CALL(mSyscalls, connect(kFd, asSockaddrPtr(&expected), sizeof(expected)))
161         .WillOnce(Return(kError));
162     EXPECT_EQ(kError, sys.connect(kFd, expected));
163 }
164 
TEST_F(SyscallsTest,sendto)165 TEST_F(SyscallsTest, sendto) {
166     constexpr Fd kFd(40);
167     constexpr int kFlags = 0;
168     std::array<char, 10> payload;
169     const auto slice = makeSlice(payload);
170     sockaddr_nl expected = {};
171     auto& sys = sSyscalls.get();
172 
173     // Success
174     EXPECT_CALL(mSyscalls, sendto(kFd, slice, kFlags, asSockaddrPtr(&expected), sizeof(expected)))
175         .WillOnce(Return(slice.size()));
176     EXPECT_EQ(status::ok, sys.sendto(kFd, slice, kFlags, expected));
177 }
178 
TEST_F(SyscallsTest,recvfrom)179 TEST_F(SyscallsTest, recvfrom) {
180     constexpr Fd kFd(40);
181     constexpr int kFlags = 0;
182     std::array<char, 10> payload;
183     const auto dst = makeSlice(payload);
184     const auto used = take(dst, 8);
185     sockaddr_nl expected = {};
186     auto& sys = sSyscalls.get();
187 
188     // Success
189     EXPECT_CALL(mSyscalls, recvfrom(kFd, dst, kFlags, _, _))
190         .WillOnce(Invoke([expected, used](Fd, const Slice, int, sockaddr* src, socklen_t* srclen) {
191             memcpy(src, &expected, sizeof(src));
192             *srclen = sizeof(expected);
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