blob: 9ac502e3e4450b557dad124aeb9296b0a1814023 [file] [log] [blame]
Lorenzo Colittia93126d2017-08-24 13:28:19 +09001/*
2 * Copyright 2016 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 * TetherControllerTest.cpp - unit tests for TetherController.cpp
17 */
18
19#include <string>
20#include <vector>
21
22#include <fcntl.h>
23#include <unistd.h>
24#include <sys/types.h>
25#include <sys/socket.h>
26
27#include <gtest/gtest.h>
28
29#include <android-base/stringprintf.h>
30#include <android-base/strings.h>
Lorenzo Colitti5192bf72017-09-04 13:30:59 +090031#include <netdutils/StatusOr.h>
Lorenzo Colittia93126d2017-08-24 13:28:19 +090032
33#include "TetherController.h"
34#include "IptablesBaseTest.h"
35
36using android::base::Join;
37using android::base::StringPrintf;
Lorenzo Colitti5192bf72017-09-04 13:30:59 +090038using android::netdutils::StatusOr;
39using TetherStats = android::net::TetherController::TetherStats;
40using TetherStatsList = android::net::TetherController::TetherStatsList;
Lorenzo Colittia93126d2017-08-24 13:28:19 +090041
42namespace android {
43namespace net {
44
45class TetherControllerTest : public IptablesBaseTest {
46public:
47 TetherControllerTest() {
48 TetherController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
49 }
50
51protected:
52 TetherController mTetherCtrl;
53
54 int setDefaults() {
55 return mTetherCtrl.setDefaults();
56 }
57
58 const ExpectedIptablesCommands FLUSH_COMMANDS = {
59 { V4, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090060 ":tetherctrl_FORWARD -\n"
61 "-A tetherctrl_FORWARD -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090062 "COMMIT\n"
63 "*nat\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090064 ":tetherctrl_nat_POSTROUTING -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090065 "COMMIT\n" },
66 { V6, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090067 ":tetherctrl_FORWARD -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090068 "COMMIT\n"
69 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090070 ":tetherctrl_raw_PREROUTING -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090071 "COMMIT\n" },
72 };
73
74 const ExpectedIptablesCommands SETUP_COMMANDS = {
75 { V4, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090076 ":tetherctrl_FORWARD -\n"
77 "-A tetherctrl_FORWARD -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090078 "COMMIT\n"
79 "*nat\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090080 ":tetherctrl_nat_POSTROUTING -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090081 "COMMIT\n" },
82 { V6, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090083 ":tetherctrl_FORWARD -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090084 "COMMIT\n"
85 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090086 ":tetherctrl_raw_PREROUTING -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090087 "COMMIT\n" },
88 { V4, "*mangle\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090089 "-A tetherctrl_mangle_FORWARD -p tcp --tcp-flags SYN SYN "
Lorenzo Colittia93126d2017-08-24 13:28:19 +090090 "-j TCPMSS --clamp-mss-to-pmtu\n"
91 "COMMIT\n" },
92 { V4V6, "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +090093 ":tetherctrl_counters -\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090094 "COMMIT\n" },
95 };
96
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +090097 ExpectedIptablesCommands firstIPv4UpstreamCommands(const char *extIf) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +090098 std::string v4Cmd = StringPrintf(
99 "*nat\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900100 "-A tetherctrl_nat_POSTROUTING -o %s -j MASQUERADE\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900101 "COMMIT\n", extIf);
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900102 return {
103 { V4, v4Cmd },
104 };
105 }
106
107 ExpectedIptablesCommands firstIPv6UpstreamCommands() {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900108 std::string v6Cmd =
109 "*filter\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900110 "-A tetherctrl_FORWARD -g tetherctrl_counters\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900111 "COMMIT\n";
112 return {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900113 { V6, v6Cmd },
114 };
115 }
116
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900117 template<typename T>
118 void appendAll(std::vector<T>& cmds, const std::vector<T>& appendCmds) {
Remi NGUYEN VAN7e6f47c2018-03-20 14:44:12 +0900119 cmds.insert(cmds.end(), appendCmds.begin(), appendCmds.end());
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900120 }
121
122 ExpectedIptablesCommands startNatCommands(const char *intIf, const char *extIf,
123 bool withCounterChainRules) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900124 std::string rpfilterCmd = StringPrintf(
125 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900126 "-A tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900127 "COMMIT\n", intIf);
128
129 std::vector<std::string> v4Cmds = {
Tyler Wearbbe2d302018-05-02 19:59:49 +0530130 "*raw",
131 StringPrintf("-A tetherctrl_raw_PREROUTING -p tcp --dport 21 -i %s -j CT --helper ftp",
132 intIf),
Sunmeet Gillb72bff32018-05-10 11:17:04 -0700133 StringPrintf("-A tetherctrl_raw_PREROUTING -p tcp --dport 1723 -i %s -j CT --helper pptp",
134 intIf),
Tyler Wearbbe2d302018-05-02 19:59:49 +0530135 "COMMIT",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900136 "*filter",
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900137 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state"
138 " ESTABLISHED,RELATED -g tetherctrl_counters", extIf, intIf),
139 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900140 intIf, extIf),
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900141 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900142 intIf, extIf),
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900143 };
144
145 std::vector<std::string> v6Cmds = {
146 "*filter",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900147 };
148
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900149 if (withCounterChainRules) {
150 const std::vector<std::string> counterRules = {
151 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
152 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
153 };
154
155 appendAll(v4Cmds, counterRules);
156 appendAll(v6Cmds, counterRules);
157 }
158
159 appendAll(v4Cmds, {
160 "-D tetherctrl_FORWARD -j DROP",
161 "-A tetherctrl_FORWARD -j DROP",
162 "COMMIT\n",
163 });
164
165 v6Cmds.push_back("COMMIT\n");
166
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900167 return {
168 { V6, rpfilterCmd },
169 { V4, Join(v4Cmds, '\n') },
170 { V6, Join(v6Cmds, '\n') },
171 };
172 }
173
Remi NGUYEN VAN7e6f47c2018-03-20 14:44:12 +0900174 constexpr static const bool WITH_COUNTERS = true;
175 constexpr static const bool NO_COUNTERS = false;
176 constexpr static const bool WITH_IPV6 = true;
177 constexpr static const bool NO_IPV6 = false;
178 ExpectedIptablesCommands allNewNatCommands(
179 const char *intIf, const char *extIf, bool withCounterChainRules,
180 bool withIPv6Upstream) {
181
182 ExpectedIptablesCommands commands;
183 ExpectedIptablesCommands setupFirstIPv4Commands = firstIPv4UpstreamCommands(extIf);
184 ExpectedIptablesCommands startFirstNatCommands = startNatCommands(intIf, extIf,
185 withCounterChainRules);
186
187 appendAll(commands, setupFirstIPv4Commands);
188 if (withIPv6Upstream) {
189 ExpectedIptablesCommands setupFirstIPv6Commands = firstIPv6UpstreamCommands();
190 appendAll(commands, setupFirstIPv6Commands);
191 }
192 appendAll(commands, startFirstNatCommands);
193
194 return commands;
195 }
196
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900197 ExpectedIptablesCommands stopNatCommands(const char *intIf, const char *extIf) {
198 std::string rpfilterCmd = StringPrintf(
199 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900200 "-D tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900201 "COMMIT\n", intIf);
202
203 std::vector<std::string> v4Cmds = {
Tyler Wearbbe2d302018-05-02 19:59:49 +0530204 "*raw",
205 StringPrintf("-D tetherctrl_raw_PREROUTING -p tcp --dport 21 -i %s -j CT --helper ftp",
206 intIf),
Sunmeet Gillb72bff32018-05-10 11:17:04 -0700207 StringPrintf("-D tetherctrl_raw_PREROUTING -p tcp --dport 1723 -i %s -j CT --helper pptp",
208 intIf),
Tyler Wearbbe2d302018-05-02 19:59:49 +0530209 "COMMIT",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900210 "*filter",
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900211 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state"
212 " ESTABLISHED,RELATED -g tetherctrl_counters", extIf, intIf),
213 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900214 intIf, extIf),
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900215 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900216 intIf, extIf),
217 "COMMIT\n",
218 };
219
220 return {
221 { V6, rpfilterCmd },
222 { V4, Join(v4Cmds, '\n') },
223 };
224
225 }
226};
227
228TEST_F(TetherControllerTest, TestSetupIptablesHooks) {
229 mTetherCtrl.setupIptablesHooks();
230 expectIptablesRestoreCommands(SETUP_COMMANDS);
231}
232
233TEST_F(TetherControllerTest, TestSetDefaults) {
234 setDefaults();
235 expectIptablesRestoreCommands(FLUSH_COMMANDS);
236}
237
238TEST_F(TetherControllerTest, TestAddAndRemoveNat) {
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900239 // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
Remi NGUYEN VAN7e6f47c2018-03-20 14:44:12 +0900240 ExpectedIptablesCommands firstNat = allNewNatCommands(
241 "wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900242 mTetherCtrl.enableNat("wlan0", "rmnet0");
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900243 expectIptablesRestoreCommands(firstNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900244
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900245 // Start second NAT on same upstream. Expect only the counter rules to be created.
Remi NGUYEN VAN7e6f47c2018-03-20 14:44:12 +0900246 ExpectedIptablesCommands startOtherNatOnSameUpstream = startNatCommands(
247 "usb0", "rmnet0", WITH_COUNTERS);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900248 mTetherCtrl.enableNat("usb0", "rmnet0");
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900249 expectIptablesRestoreCommands(startOtherNatOnSameUpstream);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900250
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900251 // Remove the first NAT.
252 ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900253 mTetherCtrl.disableNat("wlan0", "rmnet0");
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900254 expectIptablesRestoreCommands(stopFirstNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900255
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900256 // Remove the last NAT. Expect rules to be cleared.
257 ExpectedIptablesCommands stopLastNat = stopNatCommands("usb0", "rmnet0");
258
259 appendAll(stopLastNat, FLUSH_COMMANDS);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900260 mTetherCtrl.disableNat("usb0", "rmnet0");
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900261 expectIptablesRestoreCommands(stopLastNat);
262
Remi NGUYEN VAN7e6f47c2018-03-20 14:44:12 +0900263 // Re-add a NAT removed previously: tetherctrl_counters chain rules are not re-added
264 firstNat = allNewNatCommands("wlan0", "rmnet0", NO_COUNTERS, WITH_IPV6);
Remi NGUYEN VANb5e6e7e2018-03-23 12:36:17 +0900265 mTetherCtrl.enableNat("wlan0", "rmnet0");
266 expectIptablesRestoreCommands(firstNat);
267
268 // Remove it again. Expect rules to be cleared.
269 stopLastNat = stopNatCommands("wlan0", "rmnet0");
270 appendAll(stopLastNat, FLUSH_COMMANDS);
271 mTetherCtrl.disableNat("wlan0", "rmnet0");
272 expectIptablesRestoreCommands(stopLastNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900273}
274
Remi NGUYEN VAN7e6f47c2018-03-20 14:44:12 +0900275TEST_F(TetherControllerTest, TestMultipleUpstreams) {
276 // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
277 ExpectedIptablesCommands firstNat = allNewNatCommands(
278 "wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6);
279 mTetherCtrl.enableNat("wlan0", "rmnet0");
280 expectIptablesRestoreCommands(firstNat);
281
282 // Start second NAT, on new upstream. Expect the upstream and NAT rules to be created for IPv4,
283 // but no counter rules for IPv6.
284 ExpectedIptablesCommands secondNat = allNewNatCommands(
285 "wlan0", "v4-rmnet0", WITH_COUNTERS, NO_IPV6);
286 mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
287 expectIptablesRestoreCommands(secondNat);
288
289 // Pretend that the caller has forgotten that it set up the second NAT, and asks us to do so
290 // again. Expect that we take no action.
291 const ExpectedIptablesCommands NONE = {};
292 mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
293 expectIptablesRestoreCommands(NONE);
294
295 // Remove the second NAT.
296 ExpectedIptablesCommands stopSecondNat = stopNatCommands("wlan0", "v4-rmnet0");
297 mTetherCtrl.disableNat("wlan0", "v4-rmnet0");
298 expectIptablesRestoreCommands(stopSecondNat);
299
300 // Remove the first NAT. Expect rules to be cleared.
301 ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
302 appendAll(stopFirstNat, FLUSH_COMMANDS);
303 mTetherCtrl.disableNat("wlan0", "rmnet0");
304 expectIptablesRestoreCommands(stopFirstNat);
305}
306
Lorenzo Colitti09353392017-08-24 14:20:32 +0900307std::string kTetherCounterHeaders = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900308 "Chain tetherctrl_counters (4 references)",
Lorenzo Colitti09353392017-08-24 14:20:32 +0900309 " pkts bytes target prot opt in out source destination",
310}, '\n');
311
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900312std::string kIPv4TetherCounters = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900313 "Chain tetherctrl_counters (4 references)",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900314 " pkts bytes target prot opt in out source destination",
315 " 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0",
316 " 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0",
317 " 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0",
318 " 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0",
319}, '\n');
320
321std::string kIPv6TetherCounters = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900322 "Chain tetherctrl_counters (2 references)",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900323 " pkts bytes target prot opt in out source destination",
324 " 10000 10000000 RETURN all wlan0 rmnet0 ::/0 ::/0",
325 " 20000 20000000 RETURN all rmnet0 wlan0 ::/0 ::/0",
326}, '\n');
327
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900328void expectTetherStatsEqual(const TetherController::TetherStats& expected,
329 const TetherController::TetherStats& actual) {
330 EXPECT_EQ(expected.intIface, actual.intIface);
331 EXPECT_EQ(expected.extIface, actual.extIface);
332 EXPECT_EQ(expected.rxBytes, actual.rxBytes);
333 EXPECT_EQ(expected.txBytes, actual.txBytes);
334 EXPECT_EQ(expected.rxPackets, actual.rxPackets);
335 EXPECT_EQ(expected.txPackets, actual.txPackets);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900336}
337
338TEST_F(TetherControllerTest, TestGetTetherStats) {
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900339 // Finding no headers is an error.
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900340 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900341 clearIptablesRestoreOutput();
342
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900343 // Finding only v4 or only v6 headers is an error.
344 addIptablesRestoreOutput(kTetherCounterHeaders, "");
345 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
346 clearIptablesRestoreOutput();
347
348 addIptablesRestoreOutput("", kTetherCounterHeaders);
349 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
350 clearIptablesRestoreOutput();
351
352 // Finding headers but no stats is not an error.
353 addIptablesRestoreOutput(kTetherCounterHeaders, kTetherCounterHeaders);
354 StatusOr<TetherStatsList> result = mTetherCtrl.getTetherStats();
355 ASSERT_TRUE(isOk(result));
356 TetherStatsList actual = result.value();
357 ASSERT_EQ(0U, actual.size());
358 clearIptablesRestoreOutput();
359
360
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900361 addIptablesRestoreOutput(kIPv6TetherCounters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900362 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900363 clearIptablesRestoreOutput();
364
365 // IPv4 and IPv6 counters are properly added together.
366 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900367 TetherStats expected0("wlan0", "rmnet0", 20002002, 20027, 10002373, 10026);
368 TetherStats expected1("bt-pan", "rmnet0", 1708806, 1450, 107471, 1040);
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900369 result = mTetherCtrl.getTetherStats();
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900370 ASSERT_TRUE(isOk(result));
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900371 actual = result.value();
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900372 ASSERT_EQ(2U, actual.size());
373 expectTetherStatsEqual(expected0, result.value()[0]);
374 expectTetherStatsEqual(expected1, result.value()[1]);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900375 clearIptablesRestoreOutput();
376
Lorenzo Colitti09353392017-08-24 14:20:32 +0900377 // No stats: error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900378 addIptablesRestoreOutput("", kIPv6TetherCounters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900379 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900380 clearIptablesRestoreOutput();
381
382 addIptablesRestoreOutput(kIPv4TetherCounters, "");
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900383 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900384 clearIptablesRestoreOutput();
385
386 // Include only one pair of interfaces and things are fine.
387 std::vector<std::string> counterLines = android::base::Split(kIPv4TetherCounters, "\n");
388 std::vector<std::string> brokenCounterLines = counterLines;
389 counterLines.resize(4);
390 std::string counters = Join(counterLines, "\n") + "\n";
391 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900392 TetherStats expected1_0("wlan0", "rmnet0", 4004, 54, 4746, 52);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900393 result = mTetherCtrl.getTetherStats();
394 ASSERT_TRUE(isOk(result));
395 actual = result.value();
396 ASSERT_EQ(1U, actual.size());
397 expectTetherStatsEqual(expected1_0, actual[0]);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900398 clearIptablesRestoreOutput();
399
400 // But if interfaces aren't paired, it's always an error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900401 counterLines.resize(3);
402 counters = Join(counterLines, "\n") + "\n";
403 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900404 result = mTetherCtrl.getTetherStats();
405 ASSERT_FALSE(isOk(result));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900406 clearIptablesRestoreOutput();
407
408 // Token unit test of the fact that we return the stats in the error message which the caller
409 // ignores.
410 std::string expectedError = counters;
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900411 std::string err = result.status().msg();
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +0900412 ASSERT_LE(expectedError.size(), err.size());
413 EXPECT_TRUE(std::equal(expectedError.rbegin(), expectedError.rend(), err.rbegin()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900414}
415
416} // namespace net
417} // namespace android