| Ken Chen | d27d6c9 | 2021-10-21 22:18:59 +0800 | [diff] [blame] | 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 |  | 
|  | 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 |  | 
|  | 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 |  | 
|  | 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 |  | 
|  | 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 |  | 
|  | 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 |  | 
|  | 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 |  | 
|  | 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 |  | 
|  | 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 |  | 
|  | 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 |