blob: 1c7444294a9c8800d0426b5fbe13691f6724e2e7 [file] [log] [blame]
Jie Jiangcf749152020-07-09 22:20:58 +09001// Copyright 2020 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "patchpanel/counters_service.h"
6
7#include <memory>
Jie Jiang8fd0ace2020-09-01 14:51:57 +09008#include <net/if.h>
Jie Jiangcf749152020-07-09 22:20:58 +09009#include <string>
10#include <vector>
11
12#include <chromeos/dbus/service_constants.h>
13#include <gmock/gmock.h>
14#include <gtest/gtest.h>
15
16#include "patchpanel/fake_shill_client.h"
Hugo Benichicd27f4e2020-11-19 18:32:23 +090017#include "patchpanel/mock_firewall.h"
Jie Jiangcf749152020-07-09 22:20:58 +090018
19namespace patchpanel {
Jie Jiangcf749152020-07-09 22:20:58 +090020
Jie Jianged0b1cc2020-07-10 15:55:33 +090021using ::testing::ContainerEq;
Jie Jiangcf749152020-07-09 22:20:58 +090022using ::testing::Contains;
Jie Jianged0b1cc2020-07-10 15:55:33 +090023using ::testing::DoAll;
Jie Jiang8fd0ace2020-09-01 14:51:57 +090024using ::testing::Each;
Jie Jiangcf749152020-07-09 22:20:58 +090025using ::testing::ElementsAreArray;
Jie Jiang8fd0ace2020-09-01 14:51:57 +090026using ::testing::Lt;
Jie Jianged0b1cc2020-07-10 15:55:33 +090027using ::testing::Return;
28using ::testing::SetArgPointee;
Jie Jiang8fd0ace2020-09-01 14:51:57 +090029using ::testing::SizeIs;
Jie Jianged0b1cc2020-07-10 15:55:33 +090030
31using Counter = CountersService::Counter;
32using SourceDevice = CountersService::SourceDevice;
33
34// The following two functions should be put outside the anounymous namespace
35// otherwise they could not be found in the tests.
36std::ostream& operator<<(std::ostream& os, const Counter& counter) {
37 os << "rx_bytes:" << counter.rx_bytes << ", rx_packets:" << counter.rx_packets
38 << ", tx_bytes:" << counter.tx_bytes
39 << ", tx_packets:" << counter.tx_packets;
40 return os;
41}
42
43bool operator==(const CountersService::Counter lhs,
44 const CountersService::Counter rhs) {
45 return lhs.rx_bytes == rhs.rx_bytes && lhs.rx_packets == rhs.rx_packets &&
46 lhs.tx_bytes == rhs.tx_bytes && lhs.tx_packets == rhs.tx_packets;
47}
48
49namespace {
50// The following string is copied from the real output of iptables v1.6.2 by
51// `iptables -t mangle -L -x -v`. This output contains all the accounting
52// chains/rules for eth0 and wlan0.
53// TODO(jiejiang): presubmit checker is complaining about the line length for
54// this (and the other raw strings in this file). Find a way to make it happy.
55const char kIptablesOutput[] = R"(
56Chain PREROUTING (policy ACCEPT 22785 packets, 136093545 bytes)
57 pkts bytes target prot opt in out source destination
58 18 2196 MARK all -- arcbr0 any anywhere anywhere MARK set 0x1
59 0 0 MARK all -- vmtap+ any anywhere anywhere MARK set 0x1
60 6526 68051766 MARK all -- arc_eth0 any anywhere anywhere MARK set 0x1
61 9 1104 MARK all -- arc_wlan0 any anywhere anywhere MARK set 0x1
62
63Chain INPUT (policy ACCEPT 4421 packets, 2461233 bytes)
64 pkts bytes target prot opt in out source destination
Hugo Benichi33af8f72020-11-20 10:08:47 +090065 312491 1767147156 rx_eth0 all -- eth0 any anywhere anywhere
66 0 0 rx_wlan0 all -- wlan0 any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +090067
68Chain FORWARD (policy ACCEPT 18194 packets, 133612816 bytes)
69 pkts bytes target prot opt in out source destination
Hugo Benichi33af8f72020-11-20 10:08:47 +090070 6511 68041668 tx_eth0 all -- any eth0 anywhere anywhere
71 11683 65571148 rx_eth0 all -- eth0 any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +090072
73Chain OUTPUT (policy ACCEPT 4574 packets, 2900995 bytes)
74 pkts bytes target prot opt in out source destination
75
76Chain POSTROUTING (policy ACCEPT 22811 packets, 136518827 bytes)
77 pkts bytes target prot opt in out source destination
Hugo Benichi33af8f72020-11-20 10:08:47 +090078 202160 1807550291 tx_eth0 all -- any eth0 anywhere anywhere owner socket exists
79 2 96 tx_wlan0 all -- any wlan0 anywhere anywhere owner socket exists
Jie Jianged0b1cc2020-07-10 15:55:33 +090080
Hugo Benichi33af8f72020-11-20 10:08:47 +090081Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +090082 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +090083 1366 244427 RETURN all -- any any anywhere anywhere mark match 0x100/0x3f00
84 0 0 RETURN all -- any any anywhere anywhere mark match 0x200/0x3f00
85 20 1670 RETURN all -- any any anywhere anywhere mark match 0x300/0x3f00
86 550 138402 RETURN all -- any any anywhere anywhere mark match 0x400/0x3f00
87 0 0 RETURN all -- any any anywhere anywhere mark match 0x500/0x3f00
88 5374 876172 RETURN all -- any any anywhere anywhere mark match 0x2000/0x3f00
89 39 2690 RETURN all -- any any anywhere anywhere mark match 0x2100/0x3f00
90 0 0 RETURN all -- any any anywhere anywhere mark match 0x2200/0x3f00
91 0 0 RETURN all -- any any anywhere anywhere mark match 0x2300/0x3f00
92 0 0 RETURN all -- any any anywhere anywhere mark match 0x2400/0x3f00
Jie Jianged0b1cc2020-07-10 15:55:33 +090093
Hugo Benichi33af8f72020-11-20 10:08:47 +090094Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +090095 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +090096 310 57004 RETURN all -- any any anywhere anywhere mark match 0x100/0x3f00
97 0 0 RETURN all -- any any anywhere anywhere mark match 0x200/0x3f00
98 0 0 RETURN all -- any any anywhere anywhere mark match 0x300/0x3f00
99 24 2801 RETURN all -- any any anywhere anywhere mark match 0x400/0x3f00
100 0 0 RETURN all -- any any anywhere anywhere mark match 0x500/0x3f00
101 0 0 RETURN all -- any any anywhere anywhere mark match 0x2000/0x3f00
102 0 0 RETURN all -- any any anywhere anywhere mark match 0x2100/0x3f00
103 0 0 RETURN all -- any any anywhere anywhere mark match 0x2200/0x3f00
104 0 0 RETURN all -- any any anywhere anywhere mark match 0x2300/0x3f00
105 0 0 RETURN all -- any any anywhere anywhere mark match 0x2400/0x3f00
Jie Jianged0b1cc2020-07-10 15:55:33 +0900106
Hugo Benichi33af8f72020-11-20 10:08:47 +0900107Chain rx_eth0 (2 references)
Hugo Benichi92fa2032020-11-20 17:47:32 +0900108 pkts bytes target prot opt in out source destination
109 73 11938 RETURN all -- any any anywhere anywhere mark match 0x100/0x3f00
110 0 0 RETURN all -- any any anywhere anywhere mark match 0x200/0x3f00
111 0 0 RETURN all -- any any anywhere anywhere mark match 0x300/0x3f00
112 5 694 RETURN all -- any any anywhere anywhere mark match 0x400/0x3f00
113 0 0 RETURN all -- any any anywhere anywhere mark match 0x500/0x3f00
114 0 0 RETURN all -- any any anywhere anywhere mark match 0x2000/0x3f00
115 0 0 RETURN all -- any any anywhere anywhere mark match 0x2100/0x3f00
116 0 0 RETURN all -- any any anywhere anywhere mark match 0x2200/0x3f00
117 0 0 RETURN all -- any any anywhere anywhere mark match 0x2300/0x3f00
118 0 0 RETURN all -- any any anywhere anywhere mark match 0x2400/0x3f00
Jie Jianged0b1cc2020-07-10 15:55:33 +0900119
Hugo Benichi33af8f72020-11-20 10:08:47 +0900120Chain rx_wlan0 (2 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900121 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900122 153 28098 RETURN all -- any any anywhere anywhere mark match 0x100/0x3f00
123 0 0 RETURN all -- any any anywhere anywhere mark match 0x200/0x3f00
124 0 0 RETURN all -- any any anywhere anywhere mark match 0x300/0x3f00
125 6 840 RETURN all -- any any anywhere anywhere mark match 0x400/0x3f00
126 0 0 RETURN all -- any any anywhere anywhere mark match 0x500/0x3f00
127 0 0 RETURN all -- any any anywhere anywhere mark match 0x2000/0x3f00
128 0 0 RETURN all -- any any anywhere anywhere mark match 0x2100/0x3f00
129 0 0 RETURN all -- any any anywhere anywhere mark match 0x2200/0x3f00
130 0 0 RETURN all -- any any anywhere anywhere mark match 0x2300/0x3f00
131 0 0 RETURN all -- any any anywhere anywhere mark match 0x2400/0x3f00
Jie Jianged0b1cc2020-07-10 15:55:33 +0900132)";
133
Jie Jiangcf749152020-07-09 22:20:58 +0900134class MockProcessRunner : public MinijailedProcessRunner {
135 public:
136 MockProcessRunner() = default;
137 ~MockProcessRunner() = default;
138
139 MOCK_METHOD(int,
140 iptables,
141 (const std::string& table,
142 const std::vector<std::string>& argv,
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900143 bool log_failures,
144 std::string* output),
Jie Jiangcf749152020-07-09 22:20:58 +0900145 (override));
146 MOCK_METHOD(int,
147 ip6tables,
148 (const std::string& table,
149 const std::vector<std::string>& argv,
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900150 bool log_failures,
151 std::string* output),
Jie Jiangcf749152020-07-09 22:20:58 +0900152 (override));
153};
154
155class CountersServiceTest : public testing::Test {
156 protected:
157 void SetUp() override {
158 fake_shill_client_ = shill_helper_.FakeClient();
Hugo Benichicd27f4e2020-11-19 18:32:23 +0900159 datapath_ = std::make_unique<Datapath>(&runner_, &firewall_);
160 counters_svc_ = std::make_unique<CountersService>(
161 fake_shill_client_.get(), datapath_.get(), &runner_);
Jie Jiangcf749152020-07-09 22:20:58 +0900162 }
163
Jie Jianged0b1cc2020-07-10 15:55:33 +0900164 // Makes `iptables` returning a bad |output|. Expects an empty map from
165 // GetCounters().
166 void TestBadIptablesOutput(const std::string& output) {
167 EXPECT_CALL(runner_, iptables(_, _, _, _))
168 .WillRepeatedly(DoAll(SetArgPointee<3>(output), Return(0)));
169 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
170 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
171
172 auto actual = counters_svc_->GetCounters({});
173 std::map<SourceDevice, Counter> expected;
174
175 EXPECT_THAT(actual, ContainerEq(expected));
176 }
177
178 // Makes `ip6tables` returning a bad |output|. Expects an empty map from
179 // GetCounters().
180 void TestBadIp6tablesOutput(const std::string& output) {
181 EXPECT_CALL(runner_, iptables(_, _, _, _))
182 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
183 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
184 .WillRepeatedly(DoAll(SetArgPointee<3>(output), Return(0)));
185
186 auto actual = counters_svc_->GetCounters({});
187 std::map<SourceDevice, Counter> expected;
188
189 EXPECT_THAT(actual, ContainerEq(expected));
190 }
191
Jie Jiangcf749152020-07-09 22:20:58 +0900192 FakeShillClientHelper shill_helper_;
193 MockProcessRunner runner_;
Hugo Benichicd27f4e2020-11-19 18:32:23 +0900194 MockFirewall firewall_;
Jie Jiangcf749152020-07-09 22:20:58 +0900195 std::unique_ptr<FakeShillClient> fake_shill_client_;
Hugo Benichicd27f4e2020-11-19 18:32:23 +0900196 std::unique_ptr<Datapath> datapath_;
Jie Jiangcf749152020-07-09 22:20:58 +0900197 std::unique_ptr<CountersService> counters_svc_;
198};
199
200TEST_F(CountersServiceTest, OnNewDevice) {
Jie Jiangcf749152020-07-09 22:20:58 +0900201 // The following commands are expected when eth0 comes up.
202 const std::vector<std::vector<std::string>> expected_calls{
Hugo Benichi33af8f72020-11-20 10:08:47 +0900203 {"-N", "rx_eth0", "-w"},
Hugo Benichiaf2021b2020-11-20 14:07:16 +0900204 {"-N", "tx_eth0", "-w"},
Hugo Benichi33af8f72020-11-20 10:08:47 +0900205 {"-A", "INPUT", "-i", "eth0", "-j", "rx_eth0", "-w"},
206 {"-A", "FORWARD", "-i", "eth0", "-j", "rx_eth0", "-w"},
Hugo Benichi33af8f72020-11-20 10:08:47 +0900207 {"-A", "POSTROUTING", "-o", "eth0", "-j", "tx_eth0", "-w"},
Hugo Benichiaf2021b2020-11-20 14:07:16 +0900208 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
209 "RETURN", "-w"},
210 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
211 "RETURN", "-w"},
212 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
213 "RETURN", "-w"},
214 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
215 "RETURN", "-w"},
216 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
217 "RETURN", "-w"},
218 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
219 "RETURN", "-w"},
220 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
221 "RETURN", "-w"},
222 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
223 "RETURN", "-w"},
224 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
225 "RETURN", "-w"},
226 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
227 "RETURN", "-w"},
228 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
229 "RETURN", "-w"},
230 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
231 "RETURN", "-w"},
232 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
233 "RETURN", "-w"},
234 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
235 "RETURN", "-w"},
236 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
237 "RETURN", "-w"},
238 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
239 "RETURN", "-w"},
240 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
241 "RETURN", "-w"},
242 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
243 "RETURN", "-w"},
244 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
245 "RETURN", "-w"},
246 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
247 "RETURN", "-w"},
Jie Jiangcf749152020-07-09 22:20:58 +0900248 };
249
250 for (const auto& rule : expected_calls) {
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900251 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
252 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
Jie Jiangcf749152020-07-09 22:20:58 +0900253 }
254
255 std::vector<dbus::ObjectPath> devices = {dbus::ObjectPath("/device/eth0")};
256 fake_shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty,
257 brillo::Any(devices));
258}
259
260TEST_F(CountersServiceTest, OnSameDeviceAppearAgain) {
Hugo Benichiddf00842020-11-20 10:24:08 +0900261 // Makes the chain creation commands return false (we already have these
262 // rules).
263 EXPECT_CALL(runner_, iptables(_, Contains("-N"), _, _))
264 .WillRepeatedly(Return(1));
265 EXPECT_CALL(runner_, ip6tables(_, Contains("-N"), _, _))
266 .WillRepeatedly(Return(1));
Jie Jiangcf749152020-07-09 22:20:58 +0900267
268 // Creating chains commands are expected but no more creating rules command
269 // (with "-I" or "-A") should come.
Hugo Benichiddf00842020-11-20 10:24:08 +0900270 EXPECT_CALL(runner_, iptables(_, Contains("-A"), _, _)).Times(0);
271 EXPECT_CALL(runner_, ip6tables(_, Contains("-A"), _, _)).Times(0);
272 EXPECT_CALL(runner_, iptables(_, Contains("-I"), _, _)).Times(0);
273 EXPECT_CALL(runner_, ip6tables(_, Contains("-I"), _, _)).Times(0);
Jie Jiangcf749152020-07-09 22:20:58 +0900274
275 std::vector<dbus::ObjectPath> devices = {dbus::ObjectPath("/device/eth0")};
276 fake_shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty,
277 brillo::Any(devices));
278}
279
Jie Jiang8fd0ace2020-09-01 14:51:57 +0900280TEST_F(CountersServiceTest, ChainNameLength) {
Jie Jiang8fd0ace2020-09-01 14:51:57 +0900281 // The name of a new chain must be shorter than 29 characters, otherwise
282 // iptables will reject the request. Uses Each() here for simplicity since no
283 // other params could be longer than 29 for now.
284 static constexpr int kMaxChainNameLength = 29;
285 EXPECT_CALL(runner_, iptables(_, Each(SizeIs(Lt(kMaxChainNameLength))), _, _))
286 .Times(AnyNumber());
287 EXPECT_CALL(runner_,
288 ip6tables(_, Each(SizeIs(Lt(kMaxChainNameLength))), _, _))
289 .Times(AnyNumber());
290
291 static const std::string kLongInterfaceName(IFNAMSIZ, 'a');
292 std::vector<dbus::ObjectPath> devices = {
293 dbus::ObjectPath("/device/" + kLongInterfaceName)};
294 fake_shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty,
295 brillo::Any(devices));
296}
297
Jie Jianged0b1cc2020-07-10 15:55:33 +0900298TEST_F(CountersServiceTest, QueryTrafficCounters) {
299 EXPECT_CALL(runner_, iptables(_, _, _, _))
300 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
301 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
302 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
303
304 auto actual = counters_svc_->GetCounters({});
305
Hugo Benichi92fa2032020-11-20 17:47:32 +0900306 // The expected counters for eth0 and wlan0. All values are doubled because
307 // the same output will be returned for both iptables and ip6tables in the
308 // tests.
Jie Jianged0b1cc2020-07-10 15:55:33 +0900309 std::map<SourceDevice, Counter> expected{
Hugo Benichi92fa2032020-11-20 17:47:32 +0900310 {{TrafficCounter::CHROME, "eth0"},
311 {23876 /*rx_bytes*/, 146 /*rx_packets*/, 488854 /*tx_bytes*/,
312 2732 /*tx_packets*/}},
313 {{TrafficCounter::UPDATE_ENGINE, "eth0"},
314 {0 /*rx_bytes*/, 0 /*rx_packets*/, 3340 /*tx_bytes*/,
315 40 /*tx_packets*/}},
316 {{TrafficCounter::SYSTEM, "eth0"},
317 {1388 /*rx_bytes*/, 10 /*rx_packets*/, 276804 /*tx_bytes*/,
318 1100 /*tx_packets*/}},
319 {{TrafficCounter::ARC, "eth0"},
320 {0 /*rx_bytes*/, 0 /*rx_packets*/, 1752344 /*tx_bytes*/,
321 10748 /*tx_packets*/}},
322 {{TrafficCounter::CROSVM, "eth0"},
323 {0 /*rx_bytes*/, 0 /*rx_packets*/, 5380 /*tx_bytes*/,
324 78 /*tx_packets*/}},
325 {{TrafficCounter::CHROME, "wlan0"},
326 {56196 /*rx_bytes*/, 306 /*rx_packets*/, 114008 /*tx_bytes*/,
327 620 /*tx_packets*/}},
328 {{TrafficCounter::SYSTEM, "wlan0"},
329 {1680 /*rx_bytes*/, 12 /*rx_packets*/, 5602 /*tx_bytes*/,
330 48 /*tx_packets*/}}};
Jie Jianged0b1cc2020-07-10 15:55:33 +0900331
332 EXPECT_THAT(actual, ContainerEq(expected));
333}
334
335TEST_F(CountersServiceTest, QueryTrafficCountersWithFilter) {
336 EXPECT_CALL(runner_, iptables(_, _, _, _))
337 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
338 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
339 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
340
341 // Only counters for eth0 should be returned. eth1 should be ignored.
342 auto actual = counters_svc_->GetCounters({"eth0", "eth1"});
343
Hugo Benichi92fa2032020-11-20 17:47:32 +0900344 // The expected counters for eth0. All values are doubled because
345 // the same output will be returned for both iptables and ip6tables in the
346 // tests.
Jie Jianged0b1cc2020-07-10 15:55:33 +0900347 std::map<SourceDevice, Counter> expected{
Hugo Benichi92fa2032020-11-20 17:47:32 +0900348 {{TrafficCounter::CHROME, "eth0"},
349 {23876 /*rx_bytes*/, 146 /*rx_packets*/, 488854 /*tx_bytes*/,
350 2732 /*tx_packets*/}},
351 {{TrafficCounter::UPDATE_ENGINE, "eth0"},
352 {0 /*rx_bytes*/, 0 /*rx_packets*/, 3340 /*tx_bytes*/,
353 40 /*tx_packets*/}},
354 {{TrafficCounter::SYSTEM, "eth0"},
355 {1388 /*rx_bytes*/, 10 /*rx_packets*/, 276804 /*tx_bytes*/,
356 1100 /*tx_packets*/}},
357 {{TrafficCounter::ARC, "eth0"},
358 {0 /*rx_bytes*/, 0 /*rx_packets*/, 1752344 /*tx_bytes*/,
359 10748 /*tx_packets*/}},
360 {{TrafficCounter::CROSVM, "eth0"},
361 {0 /*rx_bytes*/, 0 /*rx_packets*/, 5380 /*tx_bytes*/,
362 78 /*tx_packets*/}},
Jie Jianged0b1cc2020-07-10 15:55:33 +0900363 };
364
365 EXPECT_THAT(actual, ContainerEq(expected));
366}
367
368TEST_F(CountersServiceTest, QueryTrafficCountersWithEmptyIPv4Output) {
369 const std::string kEmptyOutput = "";
370 TestBadIptablesOutput(kEmptyOutput);
371}
372
373TEST_F(CountersServiceTest, QueryTrafficCountersWithEmptyIPv6Output) {
374 const std::string kEmptyOutput = "";
375 TestBadIp6tablesOutput(kEmptyOutput);
376}
377
378TEST_F(CountersServiceTest, QueryTrafficCountersWithOnlyChainName) {
379 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900380Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900381 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900382 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900383
Hugo Benichi92fa2032020-11-20 17:47:32 +0900384Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900385)";
386 TestBadIptablesOutput(kBadOutput);
387}
388
389TEST_F(CountersServiceTest, QueryTrafficCountersWithOnlyChainNameAndHeader) {
390 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900391Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900392 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900393 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900394
395Chain tx_fwd_wlan0 (1 references)
396 pkts bytes target prot opt in out source destination
397)";
398 TestBadIptablesOutput(kBadOutput);
399}
400
401TEST_F(CountersServiceTest, QueryTrafficCountersWithNotFinishedCountersLine) {
402 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900403Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900404 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900405 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900406
Hugo Benichi92fa2032020-11-20 17:47:32 +0900407Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900408 pkts bytes target prot opt in out source destination pkts bytes target prot opt in out source destination
409 0 )";
410 TestBadIptablesOutput(kBadOutput);
411}
412
Jie Jiangcf749152020-07-09 22:20:58 +0900413} // namespace
414} // namespace patchpanel