blob: 5468ed2bc0c5b9f7c6f9e1e00f15a9d7ffa74ed1 [file] [log] [blame]
Joel Scherpelzf3fa5cc2017-05-22 12:30:03 +09001/*
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
Joel Scherpelzde937962017-06-01 13:20:21 +090033using testing::ByMove;
Joel Scherpelzf3fa5cc2017-05-22 12:30:03 +090034using testing::DoAll;
Joel Scherpelzf3fa5cc2017-05-22 12:30:03 +090035using testing::Invoke;
Joel Scherpelzde937962017-06-01 13:20:21 +090036using testing::Mock;
Joel Scherpelzf3fa5cc2017-05-22 12:30:03 +090037using testing::Return;
38using testing::StrictMock;
39using testing::_;
40
41namespace android {
42namespace netdutils {
43
44class SyscallsTest : public testing::Test {
45 protected:
46 StrictMock<ScopedMockSyscalls> mSyscalls;
47};
48
49TEST(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
Joel Scherpelzde937962017-06-01 13:20:21 +090058TEST_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))));
Erik Klineb1157dd2018-05-30 20:19:08 +090065 EXPECT_CALL(mSyscalls, close(kFd)).WillOnce(Return(status::ok));
Joel Scherpelzde937962017-06-01 13:20:21 +090066 auto result = sys.open(kPath, kFlags, kMode);
67 EXPECT_EQ(status::ok, result.status());
68 EXPECT_EQ(kFd, result.value());
69}
70
Joel Scherpelzf3fa5cc2017-05-22 12:30:03 +090071TEST_F(SyscallsTest, getsockname) {
72 constexpr Fd kFd(40);
73 sockaddr_nl expected = {};
74 auto& sys = sSyscalls.get();
75
76 // Success
77 EXPECT_CALL(mSyscalls, getsockname(kFd, _, _))
78 .WillOnce(Invoke([expected](Fd, sockaddr* addr, socklen_t* addrlen) {
79 memcpy(addr, &expected, sizeof(expected));
80 EXPECT_EQ(*addrlen, static_cast<socklen_t>(sizeof(expected)));
81 return status::ok;
82 }));
83 const auto result = sys.getsockname<sockaddr_nl>(kFd);
84 EXPECT_TRUE(isOk(result));
85 EXPECT_EQ(expected, result.value());
86
87 // Failure
88 const Status kError = statusFromErrno(EINVAL, "test");
89 EXPECT_CALL(mSyscalls, getsockname(kFd, _, _)).WillOnce(Return(kError));
90 EXPECT_EQ(kError, sys.getsockname<sockaddr_nl>(kFd).status());
91}
92
93TEST_F(SyscallsTest, setsockopt) {
94 constexpr Fd kFd(40);
95 constexpr int kLevel = 50;
96 constexpr int kOptname = 70;
97 sockaddr_nl expected = {};
98 auto& sys = sSyscalls.get();
99
100 // Success
101 EXPECT_CALL(mSyscalls, setsockopt(kFd, kLevel, kOptname, &expected, sizeof(expected)))
102 .WillOnce(Return(status::ok));
103 EXPECT_EQ(status::ok, sys.setsockopt(kFd, kLevel, kOptname, expected));
104
105 // Failure
106 const Status kError = statusFromErrno(EINVAL, "test");
107 EXPECT_CALL(mSyscalls, setsockopt(kFd, kLevel, kOptname, &expected, sizeof(expected)))
108 .WillOnce(Return(kError));
109 EXPECT_EQ(kError, sys.setsockopt(kFd, kLevel, kOptname, expected));
110}
111
Benedict Wongb2daefb2017-12-06 22:05:46 -0800112TEST_F(SyscallsTest, getsockopt) {
113 constexpr Fd kFd(40);
114 constexpr int kLevel = 50;
115 constexpr int kOptname = 70;
116 sockaddr_nl expected = {};
117 socklen_t optLen = 0;
118 auto& sys = sSyscalls.get();
119
120 // Success
121 EXPECT_CALL(mSyscalls, getsockopt(kFd, kLevel, kOptname, &expected, &optLen))
122 .WillOnce(Return(status::ok));
123 EXPECT_EQ(status::ok, sys.getsockopt(kFd, kLevel, kOptname, &expected, &optLen));
124
125 // Failure
126 const Status kError = statusFromErrno(EINVAL, "test");
127 EXPECT_CALL(mSyscalls, getsockopt(kFd, kLevel, kOptname, &expected, &optLen))
128 .WillOnce(Return(kError));
129 EXPECT_EQ(kError, sys.getsockopt(kFd, kLevel, kOptname, &expected, &optLen));
130}
131
Joel Scherpelzf3fa5cc2017-05-22 12:30:03 +0900132TEST_F(SyscallsTest, bind) {
133 constexpr Fd kFd(40);
134 sockaddr_nl expected = {};
135 auto& sys = sSyscalls.get();
136
137 // Success
138 EXPECT_CALL(mSyscalls, bind(kFd, asSockaddrPtr(&expected), sizeof(expected)))
139 .WillOnce(Return(status::ok));
140 EXPECT_EQ(status::ok, sys.bind(kFd, expected));
141
142 // Failure
143 const Status kError = statusFromErrno(EINVAL, "test");
144 EXPECT_CALL(mSyscalls, bind(kFd, asSockaddrPtr(&expected), sizeof(expected)))
145 .WillOnce(Return(kError));
146 EXPECT_EQ(kError, sys.bind(kFd, expected));
147}
148
149TEST_F(SyscallsTest, connect) {
150 constexpr Fd kFd(40);
151 sockaddr_nl expected = {};
152 auto& sys = sSyscalls.get();
153
154 // Success
155 EXPECT_CALL(mSyscalls, connect(kFd, asSockaddrPtr(&expected), sizeof(expected)))
156 .WillOnce(Return(status::ok));
157 EXPECT_EQ(status::ok, sys.connect(kFd, expected));
158
159 // Failure
160 const Status kError = statusFromErrno(EINVAL, "test");
161 EXPECT_CALL(mSyscalls, connect(kFd, asSockaddrPtr(&expected), sizeof(expected)))
162 .WillOnce(Return(kError));
163 EXPECT_EQ(kError, sys.connect(kFd, expected));
164}
165
166TEST_F(SyscallsTest, sendto) {
167 constexpr Fd kFd(40);
168 constexpr int kFlags = 0;
169 std::array<char, 10> payload;
170 const auto slice = makeSlice(payload);
171 sockaddr_nl expected = {};
172 auto& sys = sSyscalls.get();
173
174 // Success
175 EXPECT_CALL(mSyscalls, sendto(kFd, slice, kFlags, asSockaddrPtr(&expected), sizeof(expected)))
176 .WillOnce(Return(slice.size()));
177 EXPECT_EQ(status::ok, sys.sendto(kFd, slice, kFlags, expected));
178}
179
180TEST_F(SyscallsTest, recvfrom) {
181 constexpr Fd kFd(40);
182 constexpr int kFlags = 0;
183 std::array<char, 10> payload;
184 const auto dst = makeSlice(payload);
185 const auto used = take(dst, 8);
186 sockaddr_nl expected = {};
187 auto& sys = sSyscalls.get();
188
189 // Success
190 EXPECT_CALL(mSyscalls, recvfrom(kFd, dst, kFlags, _, _))
191 .WillOnce(Invoke([expected, used](Fd, const Slice, int, sockaddr* src, socklen_t* srclen) {
192 memcpy(src, &expected, sizeof(src));
193 *srclen = sizeof(expected);
194 return used;
195 }));
196 auto result = sys.recvfrom<sockaddr_nl>(kFd, dst, kFlags);
197 EXPECT_EQ(status::ok, result.status());
198 EXPECT_EQ(used, result.value().first);
199 EXPECT_EQ(expected, result.value().second);
200}
201
202} // namespace netdutils
203} // namespace android