blob: 9873168512295c0bc70f55dfca88afbca4facbe4 [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>
Hungming Chen66ddfbb2020-02-21 20:31:20 +080023#include <inttypes.h>
Lorenzo Colittia93126d2017-08-24 13:28:19 +090024#include <sys/socket.h>
Hungming Chen66ddfbb2020-02-21 20:31:20 +080025#include <sys/types.h>
26#include <unistd.h>
Lorenzo Colittia93126d2017-08-24 13:28:19 +090027
28#include <gtest/gtest.h>
29
30#include <android-base/stringprintf.h>
31#include <android-base/strings.h>
Hungming Chen66ddfbb2020-02-21 20:31:20 +080032#include <gmock/gmock.h>
Lorenzo Colitti5192bf72017-09-04 13:30:59 +090033#include <netdutils/StatusOr.h>
Lorenzo Colittia93126d2017-08-24 13:28:19 +090034
Lorenzo Colittia93126d2017-08-24 13:28:19 +090035#include "IptablesBaseTest.h"
Patrick Rohr70d42502021-10-12 18:24:10 +020036#include "TcUtils.h"
Hungming Chen66ddfbb2020-02-21 20:31:20 +080037#include "TetherController.h"
Lorenzo Colittia93126d2017-08-24 13:28:19 +090038
39using android::base::Join;
40using android::base::StringPrintf;
Lorenzo Colitti5192bf72017-09-04 13:30:59 +090041using android::netdutils::StatusOr;
42using TetherStats = android::net::TetherController::TetherStats;
43using TetherStatsList = android::net::TetherController::TetherStatsList;
Lorenzo Colittia93126d2017-08-24 13:28:19 +090044
45namespace android {
46namespace net {
47
48class TetherControllerTest : public IptablesBaseTest {
49public:
50 TetherControllerTest() {
51 TetherController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
52 }
53
54protected:
55 TetherController mTetherCtrl;
Hungming Chen66ddfbb2020-02-21 20:31:20 +080056
Lorenzo Colittia93126d2017-08-24 13:28:19 +090057 int setDefaults() {
58 return mTetherCtrl.setDefaults();
59 }
60
61 const ExpectedIptablesCommands FLUSH_COMMANDS = {
Luke Huangae038f82018-11-05 11:17:31 +090062 {V4,
63 "*filter\n"
64 ":tetherctrl_FORWARD -\n"
65 "-A tetherctrl_FORWARD -j DROP\n"
66 "COMMIT\n"
67 "*nat\n"
68 ":tetherctrl_nat_POSTROUTING -\n"
69 "COMMIT\n"},
70 {V6,
71 "*filter\n"
72 ":tetherctrl_FORWARD -\n"
73 "COMMIT\n"
74 "*raw\n"
75 ":tetherctrl_raw_PREROUTING -\n"
76 "COMMIT\n"},
Lorenzo Colittia93126d2017-08-24 13:28:19 +090077 };
78
79 const ExpectedIptablesCommands SETUP_COMMANDS = {
Luke Huangae038f82018-11-05 11:17:31 +090080 {V4,
81 "*filter\n"
82 ":tetherctrl_FORWARD -\n"
83 "-A tetherctrl_FORWARD -j DROP\n"
84 "COMMIT\n"
85 "*nat\n"
86 ":tetherctrl_nat_POSTROUTING -\n"
87 "COMMIT\n"},
88 {V6,
89 "*filter\n"
90 ":tetherctrl_FORWARD -\n"
91 "COMMIT\n"
92 "*raw\n"
93 ":tetherctrl_raw_PREROUTING -\n"
94 "COMMIT\n"},
95 {V4,
96 "*mangle\n"
97 "-A tetherctrl_mangle_FORWARD -p tcp --tcp-flags SYN SYN "
98 "-j TCPMSS --clamp-mss-to-pmtu\n"
99 "COMMIT\n"},
100 {V4V6,
101 "*filter\n"
102 ":tetherctrl_counters -\n"
103 "COMMIT\n"},
104 };
105
106 const ExpectedIptablesCommands ALERT_ADD_COMMAND = {
107 {V4V6,
108 "*filter\n"
109 "-I tetherctrl_FORWARD -j bw_global_alert\n"
110 "COMMIT\n"},
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900111 };
112
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900113 ExpectedIptablesCommands firstIPv4UpstreamCommands(const char *extIf) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900114 std::string v4Cmd = StringPrintf(
115 "*nat\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900116 "-A tetherctrl_nat_POSTROUTING -o %s -j MASQUERADE\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900117 "COMMIT\n", extIf);
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900118 return {
119 { V4, v4Cmd },
120 };
121 }
122
123 ExpectedIptablesCommands firstIPv6UpstreamCommands() {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900124 std::string v6Cmd =
Luke Huangae038f82018-11-05 11:17:31 +0900125 "*filter\n"
126 "-A tetherctrl_FORWARD -g tetherctrl_counters\n"
127 "COMMIT\n";
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900128 return {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900129 { V6, v6Cmd },
130 };
131 }
132
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900133 template<typename T>
134 void appendAll(std::vector<T>& cmds, const std::vector<T>& appendCmds) {
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900135 cmds.insert(cmds.end(), appendCmds.begin(), appendCmds.end());
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900136 }
137
138 ExpectedIptablesCommands startNatCommands(const char *intIf, const char *extIf,
139 bool withCounterChainRules) {
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900140 std::string rpfilterCmd = StringPrintf(
141 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900142 "-A tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900143 "COMMIT\n", intIf);
144
145 std::vector<std::string> v4Cmds = {
hiroaki.yokoyama04f2cb52018-06-13 18:47:30 +0900146 "*raw",
147 StringPrintf(
148 "-A tetherctrl_raw_PREROUTING -p tcp --dport 21 -i %s -j CT --helper ftp",
149 intIf),
150 StringPrintf("-A tetherctrl_raw_PREROUTING -p tcp --dport 1723 -i %s -j CT "
151 "--helper pptp",
152 intIf),
153 "COMMIT",
154 "*filter",
155 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state"
156 " ESTABLISHED,RELATED -g tetherctrl_counters",
157 extIf, intIf),
158 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
159 intIf, extIf),
160 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters", intIf,
161 extIf),
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900162 };
163
164 std::vector<std::string> v6Cmds = {
165 "*filter",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900166 };
167
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900168 if (withCounterChainRules) {
169 const std::vector<std::string> counterRules = {
170 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
171 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
172 };
173
174 appendAll(v4Cmds, counterRules);
175 appendAll(v6Cmds, counterRules);
176 }
177
178 appendAll(v4Cmds, {
179 "-D tetherctrl_FORWARD -j DROP",
180 "-A tetherctrl_FORWARD -j DROP",
181 "COMMIT\n",
182 });
183
184 v6Cmds.push_back("COMMIT\n");
185
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900186 return {
187 { V6, rpfilterCmd },
188 { V4, Join(v4Cmds, '\n') },
189 { V6, Join(v6Cmds, '\n') },
190 };
191 }
192
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900193 constexpr static const bool WITH_COUNTERS = true;
194 constexpr static const bool NO_COUNTERS = false;
195 constexpr static const bool WITH_IPV6 = true;
196 constexpr static const bool NO_IPV6 = false;
Luke Huangae038f82018-11-05 11:17:31 +0900197 ExpectedIptablesCommands allNewNatCommands(const char* intIf, const char* extIf,
198 bool withCounterChainRules, bool withIPv6Upstream,
199 bool firstEnableNat) {
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900200 ExpectedIptablesCommands commands;
201 ExpectedIptablesCommands setupFirstIPv4Commands = firstIPv4UpstreamCommands(extIf);
202 ExpectedIptablesCommands startFirstNatCommands = startNatCommands(intIf, extIf,
203 withCounterChainRules);
204
205 appendAll(commands, setupFirstIPv4Commands);
206 if (withIPv6Upstream) {
207 ExpectedIptablesCommands setupFirstIPv6Commands = firstIPv6UpstreamCommands();
208 appendAll(commands, setupFirstIPv6Commands);
209 }
Luke Huangae038f82018-11-05 11:17:31 +0900210 if (firstEnableNat) {
211 appendAll(commands, ALERT_ADD_COMMAND);
212 }
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900213 appendAll(commands, startFirstNatCommands);
214
215 return commands;
216 }
217
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900218 ExpectedIptablesCommands stopNatCommands(const char *intIf, const char *extIf) {
219 std::string rpfilterCmd = StringPrintf(
220 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900221 "-D tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900222 "COMMIT\n", intIf);
223
224 std::vector<std::string> v4Cmds = {
hiroaki.yokoyama04f2cb52018-06-13 18:47:30 +0900225 "*raw",
226 StringPrintf(
227 "-D tetherctrl_raw_PREROUTING -p tcp --dport 21 -i %s -j CT --helper ftp",
228 intIf),
229 StringPrintf("-D tetherctrl_raw_PREROUTING -p tcp --dport 1723 -i %s -j CT "
230 "--helper pptp",
231 intIf),
232 "COMMIT",
233 "*filter",
234 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state"
235 " ESTABLISHED,RELATED -g tetherctrl_counters",
236 extIf, intIf),
237 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
238 intIf, extIf),
239 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters", intIf,
240 extIf),
241 "COMMIT\n",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900242 };
243
244 return {
245 { V6, rpfilterCmd },
246 { V4, Join(v4Cmds, '\n') },
247 };
248
249 }
250};
251
252TEST_F(TetherControllerTest, TestSetupIptablesHooks) {
253 mTetherCtrl.setupIptablesHooks();
254 expectIptablesRestoreCommands(SETUP_COMMANDS);
255}
256
257TEST_F(TetherControllerTest, TestSetDefaults) {
258 setDefaults();
259 expectIptablesRestoreCommands(FLUSH_COMMANDS);
260}
261
262TEST_F(TetherControllerTest, TestAddAndRemoveNat) {
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900263 // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
Luke Huangae038f82018-11-05 11:17:31 +0900264 ExpectedIptablesCommands firstNat =
265 allNewNatCommands("wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6, true);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900266 mTetherCtrl.enableNat("wlan0", "rmnet0");
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900267 expectIptablesRestoreCommands(firstNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900268
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900269 // Start second NAT on same upstream. Expect only the counter rules to be created.
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900270 ExpectedIptablesCommands startOtherNatOnSameUpstream = startNatCommands(
271 "usb0", "rmnet0", WITH_COUNTERS);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900272 mTetherCtrl.enableNat("usb0", "rmnet0");
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900273 expectIptablesRestoreCommands(startOtherNatOnSameUpstream);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900274
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900275 // Remove the first NAT.
276 ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900277 mTetherCtrl.disableNat("wlan0", "rmnet0");
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900278 expectIptablesRestoreCommands(stopFirstNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900279
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900280 // Remove the last NAT. Expect rules to be cleared.
281 ExpectedIptablesCommands stopLastNat = stopNatCommands("usb0", "rmnet0");
282
283 appendAll(stopLastNat, FLUSH_COMMANDS);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900284 mTetherCtrl.disableNat("usb0", "rmnet0");
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900285 expectIptablesRestoreCommands(stopLastNat);
286
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900287 // Re-add a NAT removed previously: tetherctrl_counters chain rules are not re-added
Luke Huangae038f82018-11-05 11:17:31 +0900288 firstNat = allNewNatCommands("wlan0", "rmnet0", NO_COUNTERS, WITH_IPV6, true);
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900289 mTetherCtrl.enableNat("wlan0", "rmnet0");
290 expectIptablesRestoreCommands(firstNat);
291
292 // Remove it again. Expect rules to be cleared.
293 stopLastNat = stopNatCommands("wlan0", "rmnet0");
294 appendAll(stopLastNat, FLUSH_COMMANDS);
295 mTetherCtrl.disableNat("wlan0", "rmnet0");
296 expectIptablesRestoreCommands(stopLastNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900297}
298
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900299TEST_F(TetherControllerTest, TestMultipleUpstreams) {
300 // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
Luke Huangae038f82018-11-05 11:17:31 +0900301 ExpectedIptablesCommands firstNat =
302 allNewNatCommands("wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6, true);
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900303 mTetherCtrl.enableNat("wlan0", "rmnet0");
304 expectIptablesRestoreCommands(firstNat);
305
306 // Start second NAT, on new upstream. Expect the upstream and NAT rules to be created for IPv4,
307 // but no counter rules for IPv6.
Luke Huangae038f82018-11-05 11:17:31 +0900308 ExpectedIptablesCommands secondNat =
309 allNewNatCommands("wlan0", "v4-rmnet0", WITH_COUNTERS, NO_IPV6, false);
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900310 mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
311 expectIptablesRestoreCommands(secondNat);
312
313 // Pretend that the caller has forgotten that it set up the second NAT, and asks us to do so
314 // again. Expect that we take no action.
315 const ExpectedIptablesCommands NONE = {};
316 mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
317 expectIptablesRestoreCommands(NONE);
318
319 // Remove the second NAT.
320 ExpectedIptablesCommands stopSecondNat = stopNatCommands("wlan0", "v4-rmnet0");
321 mTetherCtrl.disableNat("wlan0", "v4-rmnet0");
322 expectIptablesRestoreCommands(stopSecondNat);
323
324 // Remove the first NAT. Expect rules to be cleared.
325 ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
326 appendAll(stopFirstNat, FLUSH_COMMANDS);
327 mTetherCtrl.disableNat("wlan0", "rmnet0");
328 expectIptablesRestoreCommands(stopFirstNat);
329}
330
Lorenzo Colitti09353392017-08-24 14:20:32 +0900331std::string kTetherCounterHeaders = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900332 "Chain tetherctrl_counters (4 references)",
Lorenzo Colitti09353392017-08-24 14:20:32 +0900333 " pkts bytes target prot opt in out source destination",
334}, '\n');
335
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900336std::string kIPv4TetherCounters = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900337 "Chain tetherctrl_counters (4 references)",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900338 " pkts bytes target prot opt in out source destination",
339 " 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0",
340 " 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0",
341 " 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0",
342 " 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0",
343}, '\n');
344
345std::string kIPv6TetherCounters = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900346 "Chain tetherctrl_counters (2 references)",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900347 " pkts bytes target prot opt in out source destination",
Maciej Żenczykowski392f6d72023-10-21 21:06:56 -0700348 " 10000 10000000 RETURN all -- wlan0 rmnet0 ::/0 ::/0",
349 " 20000 20000000 RETURN all -- rmnet0 wlan0 ::/0 ::/0",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900350}, '\n');
351
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900352void expectTetherStatsEqual(const TetherController::TetherStats& expected,
353 const TetherController::TetherStats& actual) {
354 EXPECT_EQ(expected.intIface, actual.intIface);
355 EXPECT_EQ(expected.extIface, actual.extIface);
356 EXPECT_EQ(expected.rxBytes, actual.rxBytes);
357 EXPECT_EQ(expected.txBytes, actual.txBytes);
358 EXPECT_EQ(expected.rxPackets, actual.rxPackets);
359 EXPECT_EQ(expected.txPackets, actual.txPackets);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900360}
361
362TEST_F(TetherControllerTest, TestGetTetherStats) {
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900363 // Finding no headers is an error.
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900364 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900365 clearIptablesRestoreOutput();
366
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900367 // Finding only v4 or only v6 headers is an error.
368 addIptablesRestoreOutput(kTetherCounterHeaders, "");
369 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
370 clearIptablesRestoreOutput();
371
372 addIptablesRestoreOutput("", kTetherCounterHeaders);
373 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
374 clearIptablesRestoreOutput();
375
376 // Finding headers but no stats is not an error.
377 addIptablesRestoreOutput(kTetherCounterHeaders, kTetherCounterHeaders);
378 StatusOr<TetherStatsList> result = mTetherCtrl.getTetherStats();
379 ASSERT_TRUE(isOk(result));
380 TetherStatsList actual = result.value();
381 ASSERT_EQ(0U, actual.size());
382 clearIptablesRestoreOutput();
383
384
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900385 addIptablesRestoreOutput(kIPv6TetherCounters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900386 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900387 clearIptablesRestoreOutput();
388
389 // IPv4 and IPv6 counters are properly added together.
390 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900391 TetherStats expected0("wlan0", "rmnet0", 20002002, 20027, 10002373, 10026);
392 TetherStats expected1("bt-pan", "rmnet0", 1708806, 1450, 107471, 1040);
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900393 result = mTetherCtrl.getTetherStats();
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900394 ASSERT_TRUE(isOk(result));
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900395 actual = result.value();
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900396 ASSERT_EQ(2U, actual.size());
397 expectTetherStatsEqual(expected0, result.value()[0]);
398 expectTetherStatsEqual(expected1, result.value()[1]);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900399 clearIptablesRestoreOutput();
400
Lorenzo Colitti09353392017-08-24 14:20:32 +0900401 // No stats: error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900402 addIptablesRestoreOutput("", kIPv6TetherCounters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900403 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900404 clearIptablesRestoreOutput();
405
406 addIptablesRestoreOutput(kIPv4TetherCounters, "");
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900407 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900408 clearIptablesRestoreOutput();
409
410 // Include only one pair of interfaces and things are fine.
411 std::vector<std::string> counterLines = android::base::Split(kIPv4TetherCounters, "\n");
412 std::vector<std::string> brokenCounterLines = counterLines;
413 counterLines.resize(4);
414 std::string counters = Join(counterLines, "\n") + "\n";
415 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900416 TetherStats expected1_0("wlan0", "rmnet0", 4004, 54, 4746, 52);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900417 result = mTetherCtrl.getTetherStats();
418 ASSERT_TRUE(isOk(result));
419 actual = result.value();
420 ASSERT_EQ(1U, actual.size());
421 expectTetherStatsEqual(expected1_0, actual[0]);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900422 clearIptablesRestoreOutput();
423
424 // But if interfaces aren't paired, it's always an error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900425 counterLines.resize(3);
426 counters = Join(counterLines, "\n") + "\n";
427 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900428 result = mTetherCtrl.getTetherStats();
429 ASSERT_FALSE(isOk(result));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900430 clearIptablesRestoreOutput();
431
432 // Token unit test of the fact that we return the stats in the error message which the caller
433 // ignores.
waynema71a0b592018-11-21 13:31:34 +0800434 // Skip header since we only saved the last line we parsed.
435 std::string expectedError = counterLines[2];
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900436 std::string err = result.status().msg();
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +0900437 ASSERT_LE(expectedError.size(), err.size());
438 EXPECT_TRUE(std::equal(expectedError.rbegin(), expectedError.rend(), err.rbegin()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900439}
440
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900441} // namespace net
442} // namespace android