blob: 014d05d1ac7cc2212da2cd91c84a79cda5fb6888 [file] [log] [blame]
Joel Scherpelzde937962017-06-01 13:20:21 +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 <gmock/gmock.h>
18#include <gtest/gtest.h>
19
20#include <netdutils/MockSyscalls.h>
21
22#include "InterfaceController.h"
23
24using testing::ByMove;
25using testing::Invoke;
26using testing::Return;
27using testing::StrictMock;
28using testing::_;
29
30namespace android {
31namespace net {
32namespace {
33
34using netdutils::Fd;
35using netdutils::ScopedMockSyscalls;
36using netdutils::Slice;
37using netdutils::Status;
38using netdutils::StatusOr;
39using netdutils::UniqueFd;
40using netdutils::makeSlice;
41using netdutils::status::ok;
42using netdutils::statusFromErrno;
43
44constexpr Fd kDevRandomFd(777);
45constexpr Fd kStableSecretFd(9999);
46const char kDevRandomPath[] = "/dev/random";
47const char kTestIface[] = "wlan5";
48const char kStableSecretProperty[] = "persist.netd.stable_secret";
49const char kStableSecretPath[] = "/proc/sys/net/ipv6/conf/wlan5/stable_secret";
50const char kTestIPv6Address[] = "\x20\x01\x0d\xb8\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10";
51const char kTestIPv6AddressString[] = "2001:db8:506:708:90a:b0c:d0e:f10";
52
53// getProperty() and setProperty() are forwarded to this mock
54class MockProperties {
55 public:
56 MOCK_CONST_METHOD2(get, std::string(const std::string& key, const std::string& dflt));
57 MOCK_CONST_METHOD2(set, Status(const std::string& key, const std::string& val));
58};
59
60} // namespace
61
62class StablePrivacyTest : public testing::Test {
63 protected:
64 void expectOpenFile(const std::string& path, const Fd fd, int err) {
65 if (err == 0) {
66 EXPECT_CALL(mSyscalls, open(path, _, _)).WillOnce(Return(ByMove(UniqueFd(fd))));
67 EXPECT_CALL(mSyscalls, close(fd)).WillOnce(Return(ok));
68 } else {
69 EXPECT_CALL(mSyscalls, open(path, _, _))
70 .WillOnce(Return(ByMove(statusFromErrno(err, "open() failed"))));
71 }
72 }
73
74 void expectReadFromDevRandom(const std::string& data) {
75 expectOpenFile(kDevRandomPath, kDevRandomFd, 0);
76 EXPECT_CALL(mSyscalls, read(kDevRandomFd, _)).WillOnce(Invoke([data](Fd, const Slice buf) {
77 EXPECT_EQ(data.size(), buf.size());
78 return take(buf, copy(buf, makeSlice(data)));
79 }));
80 }
81
82 void expectGetPropertyDefault(const std::string& key) {
83 EXPECT_CALL(mProperties, get(key, _))
84 .WillOnce(Invoke([](const std::string&, const std::string& dflt) { return dflt; }));
85 }
86
87 void expectGetProperty(const std::string& key, const std::string& val) {
88 EXPECT_CALL(mProperties, get(key, _))
89 .WillOnce(Invoke([val](const std::string&, const std::string&) { return val; }));
90 }
91
92 void expectSetProperty(const std::string& key, const std::string& val, Status status) {
93 EXPECT_CALL(mProperties, set(key, val)).WillOnce(Return(status));
94 }
95
96 void expectWriteToFile(const Fd fd, const std::string& val, int err) {
97 EXPECT_CALL(mSyscalls, write(fd, _))
98 .WillOnce(Invoke([val, err](Fd, const Slice buf) -> StatusOr<size_t> {
99 EXPECT_EQ(val, toString(buf));
100 if (err) {
101 return statusFromErrno(err, "write() failed");
102 }
103 return val.size();
104 }));
105 }
106
107 Status enableStablePrivacyAddresses(const std::string& iface) {
108 return InterfaceController::enableStablePrivacyAddresses(iface, mGet, mSet);
109 }
110
111 StrictMock<ScopedMockSyscalls> mSyscalls;
112 StrictMock<MockProperties> mProperties;
113
114 const std::function<std::string(const std::string&, const std::string&)> mGet =
115 [this](const std::string& key, const std::string& dflt) {
116 return mProperties.get(key, dflt);
117 };
118 const std::function<Status(const std::string&, const std::string&)> mSet =
119 [this](const std::string& key, const std::string& val) {
120 return mProperties.set(key, val);
121 };
122};
123
124TEST_F(StablePrivacyTest, PropertyOpenEnoent) {
125 expectOpenFile(kStableSecretPath, kStableSecretFd, ENOENT);
126 EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
127}
128
129TEST_F(StablePrivacyTest, PropertyOpenEaccess) {
130 expectOpenFile(kStableSecretPath, kStableSecretFd, EACCES);
131 EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
132}
133
134TEST_F(StablePrivacyTest, FirstBootWriteOkSetPropertyOk) {
135 expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
136 expectGetPropertyDefault(kStableSecretProperty);
137 expectReadFromDevRandom(kTestIPv6Address);
138 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
139 expectSetProperty(kStableSecretProperty, kTestIPv6AddressString, ok);
140 EXPECT_EQ(ok, enableStablePrivacyAddresses(kTestIface));
141}
142
143TEST_F(StablePrivacyTest, FirstBootWriteOkSetPropertyFail) {
144 const auto kError = statusFromErrno(EINVAL, "");
145 expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
146 expectGetPropertyDefault(kStableSecretProperty);
147 expectReadFromDevRandom(kTestIPv6Address);
148 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
149 expectSetProperty(kStableSecretProperty, kTestIPv6AddressString, kError);
150 EXPECT_EQ(kError, enableStablePrivacyAddresses(kTestIface));
151}
152
153TEST_F(StablePrivacyTest, FirstBootWriteFail) {
154 expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
155 expectGetPropertyDefault(kStableSecretProperty);
156 expectReadFromDevRandom(kTestIPv6Address);
157 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, ENOSPC);
158 EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
159}
160
161TEST_F(StablePrivacyTest, ExistingPropertyWriteOk) {
162 expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
163 expectGetProperty(kStableSecretProperty, kTestIPv6AddressString);
164 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
165 EXPECT_EQ(ok, enableStablePrivacyAddresses(kTestIface));
166}
167
168TEST_F(StablePrivacyTest, ExistingPropertyWriteFail) {
169 expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
170 expectGetProperty(kStableSecretProperty, kTestIPv6AddressString);
171 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, EACCES);
172 EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
173}
174
175} // namespace net
176} // namespace android