blob: 6e77bfe766dc43cf48d75233844e2df13cf5dbb8 [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 VAN70a269a2018-03-19 11:24:10 +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 VAN70a269a2018-03-19 11:24:10 +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 VAN70a269a2018-03-19 11:24:10 +0900117 template<typename T>
118 void appendAll(std::vector<T>& cmds, const std::vector<T>& appendCmds) {
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900119 cmds.insert(cmds.end(), appendCmds.begin(), appendCmds.end());
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +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 Wear415c44b2017-11-06 18:34:11 -0800130 "*raw",
131 StringPrintf("-A tetherctrl_raw_PREROUTING -p tcp --dport 21 -i %s -j CT --helper ftp",
132 intIf),
133 "COMMIT",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900134 "*filter",
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900135 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state"
136 " ESTABLISHED,RELATED -g tetherctrl_counters", extIf, intIf),
137 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900138 intIf, extIf),
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900139 StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900140 intIf, extIf),
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900141 };
142
143 std::vector<std::string> v6Cmds = {
144 "*filter",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900145 };
146
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900147 if (withCounterChainRules) {
148 const std::vector<std::string> counterRules = {
149 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
150 StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
151 };
152
153 appendAll(v4Cmds, counterRules);
154 appendAll(v6Cmds, counterRules);
155 }
156
157 appendAll(v4Cmds, {
158 "-D tetherctrl_FORWARD -j DROP",
159 "-A tetherctrl_FORWARD -j DROP",
160 "COMMIT\n",
161 });
162
163 v6Cmds.push_back("COMMIT\n");
164
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900165 return {
166 { V6, rpfilterCmd },
167 { V4, Join(v4Cmds, '\n') },
168 { V6, Join(v6Cmds, '\n') },
169 };
170 }
171
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900172 constexpr static const bool WITH_COUNTERS = true;
173 constexpr static const bool NO_COUNTERS = false;
174 constexpr static const bool WITH_IPV6 = true;
175 constexpr static const bool NO_IPV6 = false;
176 ExpectedIptablesCommands allNewNatCommands(
177 const char *intIf, const char *extIf, bool withCounterChainRules,
178 bool withIPv6Upstream) {
179
180 ExpectedIptablesCommands commands;
181 ExpectedIptablesCommands setupFirstIPv4Commands = firstIPv4UpstreamCommands(extIf);
182 ExpectedIptablesCommands startFirstNatCommands = startNatCommands(intIf, extIf,
183 withCounterChainRules);
184
185 appendAll(commands, setupFirstIPv4Commands);
186 if (withIPv6Upstream) {
187 ExpectedIptablesCommands setupFirstIPv6Commands = firstIPv6UpstreamCommands();
188 appendAll(commands, setupFirstIPv6Commands);
189 }
190 appendAll(commands, startFirstNatCommands);
191
192 return commands;
193 }
194
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900195 ExpectedIptablesCommands stopNatCommands(const char *intIf, const char *extIf) {
196 std::string rpfilterCmd = StringPrintf(
197 "*raw\n"
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900198 "-D tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900199 "COMMIT\n", intIf);
200
201 std::vector<std::string> v4Cmds = {
Tyler Wear415c44b2017-11-06 18:34:11 -0800202 "*raw",
203 StringPrintf("-D tetherctrl_raw_PREROUTING -p tcp --dport 21 -i %s -j CT --helper ftp",
204 intIf),
205 "COMMIT",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900206 "*filter",
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900207 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state"
208 " ESTABLISHED,RELATED -g tetherctrl_counters", extIf, intIf),
209 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900210 intIf, extIf),
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900211 StringPrintf("-D tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900212 intIf, extIf),
213 "COMMIT\n",
214 };
215
216 return {
217 { V6, rpfilterCmd },
218 { V4, Join(v4Cmds, '\n') },
219 };
220
221 }
222};
223
224TEST_F(TetherControllerTest, TestSetupIptablesHooks) {
225 mTetherCtrl.setupIptablesHooks();
226 expectIptablesRestoreCommands(SETUP_COMMANDS);
227}
228
229TEST_F(TetherControllerTest, TestSetDefaults) {
230 setDefaults();
231 expectIptablesRestoreCommands(FLUSH_COMMANDS);
232}
233
234TEST_F(TetherControllerTest, TestAddAndRemoveNat) {
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900235 // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900236 ExpectedIptablesCommands firstNat = allNewNatCommands(
237 "wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900238 mTetherCtrl.enableNat("wlan0", "rmnet0");
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900239 expectIptablesRestoreCommands(firstNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900240
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900241 // Start second NAT on same upstream. Expect only the counter rules to be created.
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900242 ExpectedIptablesCommands startOtherNatOnSameUpstream = startNatCommands(
243 "usb0", "rmnet0", WITH_COUNTERS);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900244 mTetherCtrl.enableNat("usb0", "rmnet0");
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900245 expectIptablesRestoreCommands(startOtherNatOnSameUpstream);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900246
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900247 // Remove the first NAT.
248 ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900249 mTetherCtrl.disableNat("wlan0", "rmnet0");
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900250 expectIptablesRestoreCommands(stopFirstNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900251
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900252 // Remove the last NAT. Expect rules to be cleared.
253 ExpectedIptablesCommands stopLastNat = stopNatCommands("usb0", "rmnet0");
254
255 appendAll(stopLastNat, FLUSH_COMMANDS);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900256 mTetherCtrl.disableNat("usb0", "rmnet0");
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900257 expectIptablesRestoreCommands(stopLastNat);
258
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900259 // Re-add a NAT removed previously: tetherctrl_counters chain rules are not re-added
260 firstNat = allNewNatCommands("wlan0", "rmnet0", NO_COUNTERS, WITH_IPV6);
Remi NGUYEN VAN70a269a2018-03-19 11:24:10 +0900261 mTetherCtrl.enableNat("wlan0", "rmnet0");
262 expectIptablesRestoreCommands(firstNat);
263
264 // Remove it again. Expect rules to be cleared.
265 stopLastNat = stopNatCommands("wlan0", "rmnet0");
266 appendAll(stopLastNat, FLUSH_COMMANDS);
267 mTetherCtrl.disableNat("wlan0", "rmnet0");
268 expectIptablesRestoreCommands(stopLastNat);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900269}
270
Remi NGUYEN VAN3b47c792018-03-20 14:44:12 +0900271TEST_F(TetherControllerTest, TestMultipleUpstreams) {
272 // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
273 ExpectedIptablesCommands firstNat = allNewNatCommands(
274 "wlan0", "rmnet0", WITH_COUNTERS, WITH_IPV6);
275 mTetherCtrl.enableNat("wlan0", "rmnet0");
276 expectIptablesRestoreCommands(firstNat);
277
278 // Start second NAT, on new upstream. Expect the upstream and NAT rules to be created for IPv4,
279 // but no counter rules for IPv6.
280 ExpectedIptablesCommands secondNat = allNewNatCommands(
281 "wlan0", "v4-rmnet0", WITH_COUNTERS, NO_IPV6);
282 mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
283 expectIptablesRestoreCommands(secondNat);
284
285 // Pretend that the caller has forgotten that it set up the second NAT, and asks us to do so
286 // again. Expect that we take no action.
287 const ExpectedIptablesCommands NONE = {};
288 mTetherCtrl.enableNat("wlan0", "v4-rmnet0");
289 expectIptablesRestoreCommands(NONE);
290
291 // Remove the second NAT.
292 ExpectedIptablesCommands stopSecondNat = stopNatCommands("wlan0", "v4-rmnet0");
293 mTetherCtrl.disableNat("wlan0", "v4-rmnet0");
294 expectIptablesRestoreCommands(stopSecondNat);
295
296 // Remove the first NAT. Expect rules to be cleared.
297 ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
298 appendAll(stopFirstNat, FLUSH_COMMANDS);
299 mTetherCtrl.disableNat("wlan0", "rmnet0");
300 expectIptablesRestoreCommands(stopFirstNat);
301}
302
Lorenzo Colitti09353392017-08-24 14:20:32 +0900303std::string kTetherCounterHeaders = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900304 "Chain tetherctrl_counters (4 references)",
Lorenzo Colitti09353392017-08-24 14:20:32 +0900305 " pkts bytes target prot opt in out source destination",
306}, '\n');
307
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900308std::string kIPv4TetherCounters = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900309 "Chain tetherctrl_counters (4 references)",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900310 " pkts bytes target prot opt in out source destination",
311 " 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0",
312 " 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0",
313 " 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0",
314 " 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0",
315}, '\n');
316
317std::string kIPv6TetherCounters = Join(std::vector<std::string> {
Lorenzo Colitti4604b4a2017-08-24 19:21:50 +0900318 "Chain tetherctrl_counters (2 references)",
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900319 " pkts bytes target prot opt in out source destination",
320 " 10000 10000000 RETURN all wlan0 rmnet0 ::/0 ::/0",
321 " 20000 20000000 RETURN all rmnet0 wlan0 ::/0 ::/0",
322}, '\n');
323
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900324void expectTetherStatsEqual(const TetherController::TetherStats& expected,
325 const TetherController::TetherStats& actual) {
326 EXPECT_EQ(expected.intIface, actual.intIface);
327 EXPECT_EQ(expected.extIface, actual.extIface);
328 EXPECT_EQ(expected.rxBytes, actual.rxBytes);
329 EXPECT_EQ(expected.txBytes, actual.txBytes);
330 EXPECT_EQ(expected.rxPackets, actual.rxPackets);
331 EXPECT_EQ(expected.txPackets, actual.txPackets);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900332}
333
334TEST_F(TetherControllerTest, TestGetTetherStats) {
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900335 // Finding no headers is an error.
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900336 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900337 clearIptablesRestoreOutput();
338
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900339 // Finding only v4 or only v6 headers is an error.
340 addIptablesRestoreOutput(kTetherCounterHeaders, "");
341 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
342 clearIptablesRestoreOutput();
343
344 addIptablesRestoreOutput("", kTetherCounterHeaders);
345 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
346 clearIptablesRestoreOutput();
347
348 // Finding headers but no stats is not an error.
349 addIptablesRestoreOutput(kTetherCounterHeaders, kTetherCounterHeaders);
350 StatusOr<TetherStatsList> result = mTetherCtrl.getTetherStats();
351 ASSERT_TRUE(isOk(result));
352 TetherStatsList actual = result.value();
353 ASSERT_EQ(0U, actual.size());
354 clearIptablesRestoreOutput();
355
356
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900357 addIptablesRestoreOutput(kIPv6TetherCounters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900358 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900359 clearIptablesRestoreOutput();
360
361 // IPv4 and IPv6 counters are properly added together.
362 addIptablesRestoreOutput(kIPv4TetherCounters, kIPv6TetherCounters);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900363 TetherStats expected0("wlan0", "rmnet0", 20002002, 20027, 10002373, 10026);
364 TetherStats expected1("bt-pan", "rmnet0", 1708806, 1450, 107471, 1040);
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900365 result = mTetherCtrl.getTetherStats();
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900366 ASSERT_TRUE(isOk(result));
Lorenzo Colitti38fd1362017-09-15 11:40:01 +0900367 actual = result.value();
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900368 ASSERT_EQ(2U, actual.size());
369 expectTetherStatsEqual(expected0, result.value()[0]);
370 expectTetherStatsEqual(expected1, result.value()[1]);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900371 clearIptablesRestoreOutput();
372
Lorenzo Colitti09353392017-08-24 14:20:32 +0900373 // No stats: error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900374 addIptablesRestoreOutput("", kIPv6TetherCounters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900375 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900376 clearIptablesRestoreOutput();
377
378 addIptablesRestoreOutput(kIPv4TetherCounters, "");
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900379 ASSERT_FALSE(isOk(mTetherCtrl.getTetherStats()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900380 clearIptablesRestoreOutput();
381
382 // Include only one pair of interfaces and things are fine.
383 std::vector<std::string> counterLines = android::base::Split(kIPv4TetherCounters, "\n");
384 std::vector<std::string> brokenCounterLines = counterLines;
385 counterLines.resize(4);
386 std::string counters = Join(counterLines, "\n") + "\n";
387 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti9a65ac62017-09-04 18:07:56 +0900388 TetherStats expected1_0("wlan0", "rmnet0", 4004, 54, 4746, 52);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900389 result = mTetherCtrl.getTetherStats();
390 ASSERT_TRUE(isOk(result));
391 actual = result.value();
392 ASSERT_EQ(1U, actual.size());
393 expectTetherStatsEqual(expected1_0, actual[0]);
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900394 clearIptablesRestoreOutput();
395
396 // But if interfaces aren't paired, it's always an error.
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900397 counterLines.resize(3);
398 counters = Join(counterLines, "\n") + "\n";
399 addIptablesRestoreOutput(counters, counters);
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900400 result = mTetherCtrl.getTetherStats();
401 ASSERT_FALSE(isOk(result));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900402 clearIptablesRestoreOutput();
403
404 // Token unit test of the fact that we return the stats in the error message which the caller
405 // ignores.
406 std::string expectedError = counters;
Lorenzo Colitti5192bf72017-09-04 13:30:59 +0900407 std::string err = result.status().msg();
Lorenzo Colitti9a8a9ff2017-01-31 19:06:59 +0900408 ASSERT_LE(expectedError.size(), err.size());
409 EXPECT_TRUE(std::equal(expectedError.rbegin(), expectedError.rend(), err.rbegin()));
Lorenzo Colittia93126d2017-08-24 13:28:19 +0900410}
411
412} // namespace net
413} // namespace android