Jie Jiang | cf74915 | 2020-07-09 22:20:58 +0900 | [diff] [blame^] | 1 | // 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> |
| 8 | #include <string> |
| 9 | #include <vector> |
| 10 | |
| 11 | #include <chromeos/dbus/service_constants.h> |
| 12 | #include <gmock/gmock.h> |
| 13 | #include <gtest/gtest.h> |
| 14 | |
| 15 | #include "patchpanel/fake_shill_client.h" |
| 16 | |
| 17 | namespace patchpanel { |
| 18 | namespace { |
| 19 | |
| 20 | using ::testing::Contains; |
| 21 | using ::testing::ElementsAreArray; |
| 22 | |
| 23 | class MockProcessRunner : public MinijailedProcessRunner { |
| 24 | public: |
| 25 | MockProcessRunner() = default; |
| 26 | ~MockProcessRunner() = default; |
| 27 | |
| 28 | MOCK_METHOD(int, |
| 29 | iptables, |
| 30 | (const std::string& table, |
| 31 | const std::vector<std::string>& argv, |
| 32 | bool log_failures), |
| 33 | (override)); |
| 34 | MOCK_METHOD(int, |
| 35 | ip6tables, |
| 36 | (const std::string& table, |
| 37 | const std::vector<std::string>& argv, |
| 38 | bool log_failures), |
| 39 | (override)); |
| 40 | }; |
| 41 | |
| 42 | class CountersServiceTest : public testing::Test { |
| 43 | protected: |
| 44 | void SetUp() override { |
| 45 | fake_shill_client_ = shill_helper_.FakeClient(); |
| 46 | counters_svc_ = |
| 47 | std::make_unique<CountersService>(fake_shill_client_.get(), &runner_); |
| 48 | } |
| 49 | |
| 50 | FakeShillClientHelper shill_helper_; |
| 51 | MockProcessRunner runner_; |
| 52 | std::unique_ptr<FakeShillClient> fake_shill_client_; |
| 53 | std::unique_ptr<CountersService> counters_svc_; |
| 54 | }; |
| 55 | |
| 56 | TEST_F(CountersServiceTest, OnNewDevice) { |
| 57 | // Makes the check commands return 1 (not found). |
| 58 | EXPECT_CALL(runner_, iptables(_, Contains("-C"), _)) |
| 59 | .WillRepeatedly(Return(1)); |
| 60 | EXPECT_CALL(runner_, ip6tables(_, Contains("-C"), _)) |
| 61 | .WillRepeatedly(Return(1)); |
| 62 | |
| 63 | // The following commands are expected when eth0 comes up. |
| 64 | const std::vector<std::vector<std::string>> expected_calls{ |
| 65 | {"-N", "rx_input_eth0", "-w"}, |
| 66 | {"-A", "INPUT", "-i", "eth0", "-j", "rx_input_eth0", "-w"}, |
| 67 | {"-A", "rx_input_eth0", "-w"}, |
| 68 | |
| 69 | {"-N", "rx_fwd_eth0", "-w"}, |
| 70 | {"-A", "FORWARD", "-i", "eth0", "-j", "rx_fwd_eth0", "-w"}, |
| 71 | {"-A", "rx_fwd_eth0", "-w"}, |
| 72 | |
| 73 | {"-N", "tx_postrt_eth0", "-w"}, |
| 74 | {"-A", "POSTROUTING", "-o", "eth0", "-m", "owner", "--socket-exists", |
| 75 | "-j", "tx_postrt_eth0", "-w"}, |
| 76 | {"-A", "tx_postrt_eth0", "-w"}, |
| 77 | |
| 78 | {"-N", "tx_fwd_eth0", "-w"}, |
| 79 | {"-A", "FORWARD", "-o", "eth0", "-j", "tx_fwd_eth0", "-w"}, |
| 80 | {"-A", "tx_fwd_eth0", "-w"}, |
| 81 | }; |
| 82 | |
| 83 | for (const auto& rule : expected_calls) { |
| 84 | EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _)); |
| 85 | EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _)); |
| 86 | } |
| 87 | |
| 88 | std::vector<dbus::ObjectPath> devices = {dbus::ObjectPath("/device/eth0")}; |
| 89 | fake_shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty, |
| 90 | brillo::Any(devices)); |
| 91 | } |
| 92 | |
| 93 | TEST_F(CountersServiceTest, OnSameDeviceAppearAgain) { |
| 94 | // Makes the check commands return 0 (we already have these rules). |
| 95 | EXPECT_CALL(runner_, iptables(_, Contains("-C"), _)) |
| 96 | .WillRepeatedly(Return(0)); |
| 97 | EXPECT_CALL(runner_, ip6tables(_, Contains("-C"), _)) |
| 98 | .WillRepeatedly(Return(0)); |
| 99 | |
| 100 | // Creating chains commands are expected but no more creating rules command |
| 101 | // (with "-I" or "-A") should come. |
| 102 | EXPECT_CALL(runner_, iptables(_, Contains("-N"), _)).Times(AnyNumber()); |
| 103 | EXPECT_CALL(runner_, ip6tables(_, Contains("-N"), _)).Times(AnyNumber()); |
| 104 | |
| 105 | std::vector<dbus::ObjectPath> devices = {dbus::ObjectPath("/device/eth0")}; |
| 106 | fake_shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty, |
| 107 | brillo::Any(devices)); |
| 108 | } |
| 109 | |
| 110 | } // namespace |
| 111 | } // namespace patchpanel |