Home | History | Annotate | Download | only in ethernet
      1 //
      2 // Copyright (C) 2013 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 
     17 #include "shill/ethernet/ethernet.h"
     18 
     19 #include <netinet/ether.h>
     20 #include <linux/if.h>  // NOLINT - Needs definitions from netinet/ether.h
     21 #include <linux/sockios.h>
     22 
     23 #include <memory>
     24 #include <utility>
     25 #include <vector>
     26 
     27 #include <base/memory/ref_counted.h>
     28 
     29 #include "shill/dhcp/mock_dhcp_config.h"
     30 #include "shill/dhcp/mock_dhcp_provider.h"
     31 #include "shill/ethernet/mock_ethernet_service.h"
     32 #include "shill/mock_device_info.h"
     33 #include "shill/mock_event_dispatcher.h"
     34 #include "shill/mock_log.h"
     35 #include "shill/mock_manager.h"
     36 #include "shill/mock_metrics.h"
     37 #include "shill/mock_service.h"
     38 #include "shill/net/mock_rtnl_handler.h"
     39 #include "shill/net/mock_sockets.h"
     40 #include "shill/nice_mock_control.h"
     41 #include "shill/testing.h"
     42 
     43 #if !defined(DISABLE_WIRED_8021X)
     44 #include "shill/ethernet/mock_ethernet_eap_provider.h"
     45 #include "shill/mock_eap_credentials.h"
     46 #include "shill/mock_eap_listener.h"
     47 #include "shill/supplicant/mock_supplicant_interface_proxy.h"
     48 #include "shill/supplicant/mock_supplicant_process_proxy.h"
     49 #include "shill/supplicant/wpa_supplicant.h"
     50 #endif  // DISABLE_WIRED_8021X
     51 
     52 using std::pair;
     53 using std::string;
     54 using std::vector;
     55 using testing::_;
     56 using testing::AnyNumber;
     57 using testing::EndsWith;
     58 using testing::Eq;
     59 using testing::InSequence;
     60 using testing::Mock;
     61 using testing::NiceMock;
     62 using testing::Return;
     63 using testing::ReturnRef;
     64 using testing::SetArgumentPointee;
     65 using testing::StrEq;
     66 using testing::StrictMock;
     67 
     68 namespace shill {
     69 
     70 class EthernetTest : public testing::Test {
     71  public:
     72   EthernetTest()
     73       : metrics_(nullptr),
     74         manager_(&control_interface_, nullptr, &metrics_),
     75         device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_),
     76         ethernet_(new Ethernet(&control_interface_,
     77                                &dispatcher_,
     78                                &metrics_,
     79                                &manager_,
     80                                kDeviceName,
     81                                kDeviceAddress,
     82                                kInterfaceIndex)),
     83         dhcp_config_(new MockDHCPConfig(&control_interface_,
     84                                         kDeviceName)),
     85 #if !defined(DISABLE_WIRED_8021X)
     86         eap_listener_(new MockEapListener()),
     87         mock_eap_service_(new MockService(&control_interface_,
     88                                           &dispatcher_,
     89                                           &metrics_,
     90                                           &manager_)),
     91         supplicant_interface_proxy_(
     92             new NiceMock<MockSupplicantInterfaceProxy>()),
     93         supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()),
     94 #endif  // DISABLE_WIRED_8021X
     95         mock_sockets_(new StrictMock<MockSockets>()),
     96         mock_service_(new MockEthernetService(
     97             &control_interface_, &metrics_,
     98             ethernet_->weak_ptr_factory_.GetWeakPtr())) {}
     99   ~EthernetTest() override {}
    100 
    101   void SetUp() override {
    102     ethernet_->rtnl_handler_ = &rtnl_handler_;
    103     ethernet_->sockets_.reset(mock_sockets_);  // Transfers ownership.
    104 
    105     ethernet_->set_dhcp_provider(&dhcp_provider_);
    106     ON_CALL(manager_, device_info()).WillByDefault(Return(&device_info_));
    107     EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(AnyNumber());
    108 
    109 #if !defined(DISABLE_WIRED_8021X)
    110     ethernet_->eap_listener_.reset(eap_listener_);  // Transfers ownership.
    111     EXPECT_CALL(manager_, ethernet_eap_provider())
    112         .WillRepeatedly(Return(&ethernet_eap_provider_));
    113     ethernet_eap_provider_.set_service(mock_eap_service_);
    114     // Transfers ownership.
    115     ethernet_->supplicant_process_proxy_.reset(supplicant_process_proxy_);
    116 #endif  // DISABLE_WIRED_8021X
    117 
    118     ON_CALL(*mock_service_, technology())
    119         .WillByDefault(Return(Technology::kEthernet));
    120   }
    121 
    122   void TearDown() override {
    123 #if !defined(DISABLE_WIRED_8021X)
    124     ethernet_eap_provider_.set_service(nullptr);
    125     ethernet_->eap_listener_.reset();
    126 #endif  // DISABLE_WIRED_8021X
    127     ethernet_->set_dhcp_provider(nullptr);
    128     ethernet_->sockets_.reset();
    129     Mock::VerifyAndClearExpectations(&manager_);
    130     ethernet_->Stop(nullptr, EnabledStateChangedCallback());
    131   }
    132 
    133  protected:
    134   static const char kDeviceName[];
    135   static const char kDeviceAddress[];
    136   static const char kInterfacePath[];
    137   static const int kInterfaceIndex;
    138 
    139   bool GetLinkUp() { return ethernet_->link_up_; }
    140   void SetLinkUp(bool link_up) { ethernet_->link_up_ = link_up; }
    141   const ServiceRefPtr& GetSelectedService() {
    142     return ethernet_->selected_service();
    143   }
    144   ServiceRefPtr GetService() { return ethernet_->service_; }
    145   void SetService(const EthernetServiceRefPtr& service) {
    146     ethernet_->service_ = service;
    147   }
    148   const PropertyStore& GetStore() { return ethernet_->store(); }
    149   void StartEthernet() {
    150     EXPECT_CALL(rtnl_handler_,
    151                 SetInterfaceFlags(kInterfaceIndex, IFF_UP, IFF_UP));
    152     ethernet_->Start(nullptr, EnabledStateChangedCallback());
    153   }
    154 
    155 #if !defined(DISABLE_WIRED_8021X)
    156   bool GetIsEapAuthenticated() { return ethernet_->is_eap_authenticated_; }
    157   void SetIsEapAuthenticated(bool is_eap_authenticated) {
    158     ethernet_->is_eap_authenticated_ = is_eap_authenticated;
    159   }
    160   bool GetIsEapDetected() { return ethernet_->is_eap_detected_; }
    161   void SetIsEapDetected(bool is_eap_detected) {
    162     ethernet_->is_eap_detected_ = is_eap_detected;
    163   }
    164   const SupplicantInterfaceProxyInterface* GetSupplicantInterfaceProxy() {
    165     return ethernet_->supplicant_interface_proxy_.get();
    166   }
    167   const string& GetSupplicantInterfacePath() {
    168     return ethernet_->supplicant_interface_path_;
    169   }
    170   const string& GetSupplicantNetworkPath() {
    171     return ethernet_->supplicant_network_path_;
    172   }
    173   void SetSupplicantNetworkPath(const string& network_path) {
    174     ethernet_->supplicant_network_path_ = network_path;
    175   }
    176   bool InvokeStartSupplicant() {
    177     return ethernet_->StartSupplicant();
    178   }
    179   void InvokeStopSupplicant() {
    180     return ethernet_->StopSupplicant();
    181   }
    182   bool InvokeStartEapAuthentication() {
    183     return ethernet_->StartEapAuthentication();
    184   }
    185   void StartSupplicant() {
    186     MockSupplicantInterfaceProxy* interface_proxy =
    187         ExpectCreateSupplicantInterfaceProxy();
    188     EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_, _))
    189         .WillOnce(DoAll(SetArgumentPointee<1>(string(kInterfacePath)),
    190                         Return(true)));
    191     EXPECT_TRUE(InvokeStartSupplicant());
    192     EXPECT_EQ(interface_proxy, GetSupplicantInterfaceProxy());
    193     EXPECT_EQ(kInterfacePath, GetSupplicantInterfacePath());
    194   }
    195   void TriggerOnEapDetected() { ethernet_->OnEapDetected(); }
    196   void TriggerCertification(const string& subject, uint32_t depth) {
    197     ethernet_->CertificationTask(subject, depth);
    198   }
    199   void TriggerTryEapAuthentication() {
    200     ethernet_->TryEapAuthenticationTask();
    201   }
    202 
    203   MockSupplicantInterfaceProxy* ExpectCreateSupplicantInterfaceProxy() {
    204     EXPECT_CALL(control_interface_,
    205                 CreateSupplicantInterfaceProxy(_, kInterfacePath))
    206         .WillOnce(ReturnAndReleasePointee(&supplicant_interface_proxy_));
    207     return supplicant_interface_proxy_.get();
    208   }
    209 #endif  // DISABLE_WIRED_8021X
    210 
    211   StrictMock<MockEventDispatcher> dispatcher_;
    212   NiceMockControl control_interface_;
    213   NiceMock<MockMetrics> metrics_;
    214   MockManager manager_;
    215   MockDeviceInfo device_info_;
    216   EthernetRefPtr ethernet_;
    217   MockDHCPProvider dhcp_provider_;
    218   scoped_refptr<MockDHCPConfig> dhcp_config_;
    219 
    220 #if !defined(DISABLE_WIRED_8021X)
    221   MockEthernetEapProvider ethernet_eap_provider_;
    222 
    223   // Owned by Ethernet instance, but tracked here for expectations.
    224   MockEapListener* eap_listener_;
    225 
    226   scoped_refptr<MockService> mock_eap_service_;
    227   std::unique_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
    228   MockSupplicantProcessProxy* supplicant_process_proxy_;
    229 #endif  // DISABLE_WIRED_8021X
    230 
    231   // Owned by Ethernet instance, but tracked here for expectations.
    232   MockSockets* mock_sockets_;
    233 
    234   MockRTNLHandler rtnl_handler_;
    235   scoped_refptr<MockEthernetService> mock_service_;
    236 };
    237 
    238 // static
    239 const char EthernetTest::kDeviceName[] = "eth0";
    240 const char EthernetTest::kDeviceAddress[] = "000102030405";
    241 const char EthernetTest::kInterfacePath[] = "/interface/path";
    242 const int EthernetTest::kInterfaceIndex = 123;
    243 
    244 TEST_F(EthernetTest, Construct) {
    245   EXPECT_FALSE(GetLinkUp());
    246 #if !defined(DISABLE_WIRED_8021X)
    247   EXPECT_FALSE(GetIsEapAuthenticated());
    248   EXPECT_FALSE(GetIsEapDetected());
    249   EXPECT_TRUE(GetStore().Contains(kEapAuthenticationCompletedProperty));
    250   EXPECT_TRUE(GetStore().Contains(kEapAuthenticatorDetectedProperty));
    251 #endif  // DISABLE_WIRED_8021X
    252   EXPECT_NE(nullptr, GetService().get());
    253 }
    254 
    255 TEST_F(EthernetTest, StartStop) {
    256   Service* service = GetService().get();
    257   EXPECT_CALL(manager_, RegisterService(Eq(service)));
    258   StartEthernet();
    259 
    260   EXPECT_CALL(manager_, DeregisterService(Eq(service)));
    261   ethernet_->Stop(nullptr, EnabledStateChangedCallback());
    262 
    263   // Ethernet device retains its service.
    264   EXPECT_NE(nullptr, GetService());
    265 }
    266 
    267 TEST_F(EthernetTest, LinkEvent) {
    268   StartEthernet();
    269   SetService(mock_service_);
    270 
    271   // Link-down event while already down.
    272   EXPECT_CALL(manager_, DeregisterService(_)).Times(0);
    273 #if !defined(DISABLE_WIRED_8021X)
    274   EXPECT_CALL(*eap_listener_, Start()).Times(0);
    275 #endif  // DISABLE_WIRED_8021X
    276   ethernet_->LinkEvent(0, IFF_LOWER_UP);
    277   EXPECT_FALSE(GetLinkUp());
    278 #if !defined(DISABLE_WIRED_8021X)
    279   EXPECT_FALSE(GetIsEapDetected());
    280 #endif  // DISABLE_WIRED_8021X
    281   Mock::VerifyAndClearExpectations(&manager_);
    282 
    283   // Link-up event while down.
    284   int kFakeFd = 789;
    285   EXPECT_CALL(manager_, UpdateService(IsRefPtrTo(mock_service_)));
    286   EXPECT_CALL(*mock_service_, OnVisibilityChanged());
    287 #if !defined(DISABLE_WIRED_8021X)
    288   EXPECT_CALL(*eap_listener_, Start());
    289 #endif  // DISABLE_WIRED_8021X
    290   EXPECT_CALL(*mock_sockets_, Socket(_, _, _)).WillOnce(Return(kFakeFd));
    291   EXPECT_CALL(*mock_sockets_, Ioctl(kFakeFd, SIOCETHTOOL, _));
    292   EXPECT_CALL(*mock_sockets_, Close(kFakeFd));
    293   ethernet_->LinkEvent(IFF_LOWER_UP, 0);
    294   EXPECT_TRUE(GetLinkUp());
    295 #if !defined(DISABLE_WIRED_8021X)
    296   EXPECT_FALSE(GetIsEapDetected());
    297 #endif  // DISABLE_WIRED_8021X
    298   Mock::VerifyAndClearExpectations(&manager_);
    299   Mock::VerifyAndClearExpectations(mock_service_.get());
    300 
    301   // Link-up event while already up.
    302   EXPECT_CALL(manager_, UpdateService(_)).Times(0);
    303   EXPECT_CALL(*mock_service_, OnVisibilityChanged()).Times(0);
    304 #if !defined(DISABLE_WIRED_8021X)
    305   EXPECT_CALL(*eap_listener_, Start()).Times(0);
    306 #endif  // DISABLE_WIRED_8021X
    307   ethernet_->LinkEvent(IFF_LOWER_UP, 0);
    308   EXPECT_TRUE(GetLinkUp());
    309 #if !defined(DISABLE_WIRED_8021X)
    310   EXPECT_FALSE(GetIsEapDetected());
    311 #endif  // DISABLE_WIRED_8021X
    312   Mock::VerifyAndClearExpectations(&manager_);
    313   Mock::VerifyAndClearExpectations(mock_service_.get());
    314 
    315   // Link-down event while up.
    316 #if !defined(DISABLE_WIRED_8021X)
    317   SetIsEapDetected(true);
    318   // This is done in SetUp, but we have to reestablish this after calling
    319   // VerifyAndClearExpectations() above.
    320   EXPECT_CALL(manager_, ethernet_eap_provider())
    321       .WillRepeatedly(Return(&ethernet_eap_provider_));
    322   EXPECT_CALL(ethernet_eap_provider_,
    323               ClearCredentialChangeCallback(ethernet_.get()));
    324   EXPECT_CALL(*eap_listener_, Stop());
    325 #endif  // DISABLE_WIRED_8021X
    326   EXPECT_CALL(manager_, UpdateService(IsRefPtrTo(GetService().get())));
    327   EXPECT_CALL(*mock_service_, OnVisibilityChanged());
    328   ethernet_->LinkEvent(0, IFF_LOWER_UP);
    329   EXPECT_FALSE(GetLinkUp());
    330 #if !defined(DISABLE_WIRED_8021X)
    331   EXPECT_FALSE(GetIsEapDetected());
    332 #endif  // DISABLE_WIRED_8021X
    333 
    334   // Restore this expectation during shutdown.
    335   EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(AnyNumber());
    336 }
    337 
    338 TEST_F(EthernetTest, ConnectToLinkDown) {
    339   StartEthernet();
    340   SetService(mock_service_);
    341   SetLinkUp(false);
    342   EXPECT_EQ(nullptr, GetSelectedService().get());
    343   EXPECT_CALL(dhcp_provider_, CreateIPv4Config(_, _, _, _)).Times(0);
    344   EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(0);
    345   EXPECT_CALL(dispatcher_, PostTask(_)).Times(0);
    346   EXPECT_CALL(*mock_service_, SetState(_)).Times(0);
    347   ethernet_->ConnectTo(mock_service_.get());
    348   EXPECT_EQ(nullptr, GetSelectedService().get());
    349 }
    350 
    351 TEST_F(EthernetTest, ConnectToFailure) {
    352   StartEthernet();
    353   SetService(mock_service_);
    354   SetLinkUp(true);
    355   EXPECT_EQ(nullptr, GetSelectedService().get());
    356   EXPECT_CALL(dhcp_provider_, CreateIPv4Config(_, _, _, _)).
    357       WillOnce(Return(dhcp_config_));
    358   EXPECT_CALL(*dhcp_config_.get(), RequestIP()).WillOnce(Return(false));
    359   EXPECT_CALL(dispatcher_, PostTask(_));  // Posts ConfigureStaticIPTask.
    360   EXPECT_CALL(*mock_service_, SetState(Service::kStateFailure));
    361   ethernet_->ConnectTo(mock_service_.get());
    362   EXPECT_EQ(mock_service_, GetSelectedService().get());
    363 }
    364 
    365 TEST_F(EthernetTest, ConnectToSuccess) {
    366   StartEthernet();
    367   SetService(mock_service_);
    368   SetLinkUp(true);
    369   EXPECT_EQ(nullptr, GetSelectedService().get());
    370   EXPECT_CALL(dhcp_provider_, CreateIPv4Config(_, _, _, _)).
    371       WillOnce(Return(dhcp_config_));
    372   EXPECT_CALL(*dhcp_config_.get(), RequestIP()).WillOnce(Return(true));
    373   EXPECT_CALL(dispatcher_, PostTask(_));  // Posts ConfigureStaticIPTask.
    374   EXPECT_CALL(*mock_service_, SetState(Service::kStateConfiguring));
    375   ethernet_->ConnectTo(mock_service_.get());
    376   EXPECT_EQ(GetService().get(), GetSelectedService().get());
    377   Mock::VerifyAndClearExpectations(mock_service_.get());
    378 
    379   EXPECT_CALL(*mock_service_, SetState(Service::kStateIdle));
    380   ethernet_->DisconnectFrom(mock_service_.get());
    381   EXPECT_EQ(nullptr, GetSelectedService().get());
    382 }
    383 
    384 #if !defined(DISABLE_WIRED_8021X)
    385 TEST_F(EthernetTest, OnEapDetected) {
    386   EXPECT_FALSE(GetIsEapDetected());
    387   EXPECT_CALL(*eap_listener_, Stop());
    388   EXPECT_CALL(ethernet_eap_provider_,
    389               SetCredentialChangeCallback(ethernet_.get(), _));
    390   EXPECT_CALL(dispatcher_, PostTask(_));  // Posts TryEapAuthenticationTask.
    391   TriggerOnEapDetected();
    392   EXPECT_TRUE(GetIsEapDetected());
    393 }
    394 
    395 TEST_F(EthernetTest, TryEapAuthenticationNotConnectableNotAuthenticated) {
    396   SetService(mock_service_);
    397   EXPECT_CALL(*mock_eap_service_, Is8021xConnectable()).WillOnce(Return(false));
    398   NiceScopedMockLog log;
    399   EXPECT_CALL(log, Log(logging::LOG_INFO, _,
    400                        EndsWith("EAP Service lacks 802.1X credentials; "
    401                                 "not doing EAP authentication.")));
    402   TriggerTryEapAuthentication();
    403   SetService(nullptr);
    404 }
    405 
    406 TEST_F(EthernetTest, TryEapAuthenticationNotConnectableAuthenticated) {
    407   SetService(mock_service_);
    408   SetIsEapAuthenticated(true);
    409   EXPECT_CALL(*mock_eap_service_, Is8021xConnectable()).WillOnce(Return(false));
    410   NiceScopedMockLog log;
    411   EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
    412   EXPECT_CALL(log, Log(logging::LOG_INFO, _,
    413                        EndsWith("EAP Service lost 802.1X credentials; "
    414                                 "terminating EAP authentication.")));
    415   TriggerTryEapAuthentication();
    416   EXPECT_FALSE(GetIsEapAuthenticated());
    417 }
    418 
    419 TEST_F(EthernetTest, TryEapAuthenticationEapNotDetected) {
    420   SetService(mock_service_);
    421   EXPECT_CALL(*mock_eap_service_, Is8021xConnectable()).WillOnce(Return(true));
    422   NiceScopedMockLog log;
    423   EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
    424                        EndsWith("EAP authenticator not detected; "
    425                                 "not doing EAP authentication.")));
    426   TriggerTryEapAuthentication();
    427 }
    428 
    429 TEST_F(EthernetTest, StartSupplicant) {
    430   // Save the mock proxy pointers before the Ethernet instance accepts it.
    431   MockSupplicantInterfaceProxy* interface_proxy =
    432       supplicant_interface_proxy_.get();
    433   MockSupplicantProcessProxy* process_proxy = supplicant_process_proxy_;
    434 
    435   StartSupplicant();
    436 
    437   // Starting it again should not invoke another call to create an interface.
    438   Mock::VerifyAndClearExpectations(process_proxy);
    439   EXPECT_CALL(*process_proxy, CreateInterface(_, _)).Times(0);
    440   EXPECT_TRUE(InvokeStartSupplicant());
    441 
    442   // Also, the mock pointers should remain; if the MockProxyFactory was
    443   // invoked again, they would be nullptr.
    444   EXPECT_EQ(interface_proxy, GetSupplicantInterfaceProxy());
    445   EXPECT_EQ(kInterfacePath, GetSupplicantInterfacePath());
    446 }
    447 
    448 TEST_F(EthernetTest, StartSupplicantWithInterfaceExistsException) {
    449   MockSupplicantProcessProxy* process_proxy = supplicant_process_proxy_;
    450   MockSupplicantInterfaceProxy* interface_proxy =
    451       ExpectCreateSupplicantInterfaceProxy();
    452   EXPECT_CALL(*process_proxy, CreateInterface(_, _)).WillOnce(Return(false));
    453   EXPECT_CALL(*process_proxy, GetInterface(kDeviceName, _))
    454       .WillOnce(
    455           DoAll(SetArgumentPointee<1>(string(kInterfacePath)), Return(true)));
    456   EXPECT_TRUE(InvokeStartSupplicant());
    457   EXPECT_EQ(interface_proxy, GetSupplicantInterfaceProxy());
    458   EXPECT_EQ(kInterfacePath, GetSupplicantInterfacePath());
    459 }
    460 
    461 TEST_F(EthernetTest, StartSupplicantWithUnknownException) {
    462   MockSupplicantProcessProxy* process_proxy = supplicant_process_proxy_;
    463   EXPECT_CALL(*process_proxy, CreateInterface(_, _)).WillOnce(Return(false));
    464   EXPECT_CALL(*process_proxy, GetInterface(kDeviceName, _))
    465       .WillOnce(Return(false));
    466   EXPECT_FALSE(InvokeStartSupplicant());
    467   EXPECT_EQ(nullptr, GetSupplicantInterfaceProxy());
    468   EXPECT_EQ("", GetSupplicantInterfacePath());
    469 }
    470 
    471 TEST_F(EthernetTest, StartEapAuthentication) {
    472   MockSupplicantInterfaceProxy* interface_proxy =
    473       supplicant_interface_proxy_.get();
    474 
    475   StartSupplicant();
    476   SetService(mock_service_);
    477 
    478   EXPECT_CALL(*mock_service_, ClearEAPCertification());
    479   MockEapCredentials mock_eap_credentials;
    480   EXPECT_CALL(*mock_eap_service_, eap())
    481       .WillOnce(Return(&mock_eap_credentials));
    482   EXPECT_CALL(mock_eap_credentials, PopulateSupplicantProperties(_, _));
    483   EXPECT_CALL(*interface_proxy, RemoveNetwork(_)).Times(0);
    484   EXPECT_CALL(*interface_proxy, AddNetwork(_, _))
    485       .WillOnce(Return(false));
    486   EXPECT_CALL(*interface_proxy, SelectNetwork(_)).Times(0);
    487   EXPECT_CALL(*interface_proxy, EAPLogon()).Times(0);
    488   EXPECT_FALSE(InvokeStartEapAuthentication());
    489   Mock::VerifyAndClearExpectations(mock_service_.get());
    490   Mock::VerifyAndClearExpectations(mock_eap_service_.get());
    491   Mock::VerifyAndClearExpectations(interface_proxy);
    492   EXPECT_EQ("", GetSupplicantNetworkPath());
    493 
    494   EXPECT_CALL(*mock_service_, ClearEAPCertification());
    495   EXPECT_CALL(*interface_proxy, RemoveNetwork(_)).Times(0);
    496   EXPECT_CALL(*mock_eap_service_, eap())
    497       .WillOnce(Return(&mock_eap_credentials));
    498   EXPECT_CALL(mock_eap_credentials, PopulateSupplicantProperties(_, _));
    499   const char kFirstNetworkPath[] = "/network/first-path";
    500   EXPECT_CALL(*interface_proxy, AddNetwork(_, _))
    501       .WillOnce(
    502           DoAll(SetArgumentPointee<1>(string(kFirstNetworkPath)),
    503                 Return(true)));
    504   EXPECT_CALL(*interface_proxy, SelectNetwork(StrEq(kFirstNetworkPath)));
    505   EXPECT_CALL(*interface_proxy, EAPLogon());
    506   EXPECT_TRUE(InvokeStartEapAuthentication());
    507   Mock::VerifyAndClearExpectations(mock_service_.get());
    508   Mock::VerifyAndClearExpectations(mock_eap_service_.get());
    509   Mock::VerifyAndClearExpectations(&mock_eap_credentials);
    510   Mock::VerifyAndClearExpectations(interface_proxy);
    511   EXPECT_EQ(kFirstNetworkPath, GetSupplicantNetworkPath());
    512 
    513   EXPECT_CALL(*mock_service_, ClearEAPCertification());
    514   EXPECT_CALL(*interface_proxy, RemoveNetwork(StrEq(kFirstNetworkPath)))
    515       .WillOnce(Return(true));
    516   EXPECT_CALL(*mock_eap_service_, eap())
    517       .WillOnce(Return(&mock_eap_credentials));
    518   EXPECT_CALL(mock_eap_credentials, PopulateSupplicantProperties(_, _));
    519   const char kSecondNetworkPath[] = "/network/second-path";
    520   EXPECT_CALL(*interface_proxy, AddNetwork(_, _))
    521       .WillOnce(
    522           DoAll(SetArgumentPointee<1>(string(kSecondNetworkPath)),
    523                 Return(true)));
    524   EXPECT_CALL(*interface_proxy, SelectNetwork(StrEq(kSecondNetworkPath)));
    525   EXPECT_CALL(*interface_proxy, EAPLogon());
    526   EXPECT_TRUE(InvokeStartEapAuthentication());
    527   EXPECT_EQ(kSecondNetworkPath, GetSupplicantNetworkPath());
    528 }
    529 
    530 TEST_F(EthernetTest, StopSupplicant) {
    531   MockSupplicantProcessProxy* process_proxy = supplicant_process_proxy_;
    532   MockSupplicantInterfaceProxy* interface_proxy =
    533       supplicant_interface_proxy_.get();
    534   StartSupplicant();
    535   SetIsEapAuthenticated(true);
    536   SetSupplicantNetworkPath("/network/1");
    537   EXPECT_CALL(*interface_proxy, EAPLogoff()).WillOnce(Return(true));
    538   EXPECT_CALL(*process_proxy, RemoveInterface(StrEq(kInterfacePath)))
    539       .WillOnce(Return(true));
    540   InvokeStopSupplicant();
    541   EXPECT_EQ(nullptr, GetSupplicantInterfaceProxy());
    542   EXPECT_EQ("", GetSupplicantInterfacePath());
    543   EXPECT_EQ("", GetSupplicantNetworkPath());
    544   EXPECT_FALSE(GetIsEapAuthenticated());
    545 }
    546 
    547 TEST_F(EthernetTest, Certification) {
    548   const string kSubjectName("subject-name");
    549   const uint32_t kDepth = 123;
    550   // Should not crash due to no service_.
    551   TriggerCertification(kSubjectName, kDepth);
    552   EXPECT_CALL(*mock_service_, AddEAPCertification(kSubjectName, kDepth));
    553   SetService(mock_service_);
    554   TriggerCertification(kSubjectName, kDepth);
    555 }
    556 #endif  // DISABLE_WIRED_8021X
    557 
    558 #if !defined(DISABLE_PPPOE)
    559 
    560 MATCHER_P(TechnologyEq, technology, "") {
    561   return arg->technology() == technology;
    562 }
    563 
    564 TEST_F(EthernetTest, TogglePPPoE) {
    565   SetService(mock_service_);
    566 
    567   EXPECT_CALL(*mock_service_, technology())
    568       .WillRepeatedly(Return(Technology::kEthernet));
    569   EXPECT_CALL(*mock_service_, Disconnect(_, _));
    570 
    571   InSequence sequence;
    572   EXPECT_CALL(manager_, DeregisterService(Eq(mock_service_)));
    573   EXPECT_CALL(manager_, RegisterService(TechnologyEq(Technology::kPPPoE)));
    574   EXPECT_CALL(manager_, DeregisterService(TechnologyEq(Technology::kPPPoE)));
    575   EXPECT_CALL(manager_, RegisterService(_));
    576 
    577   const vector<pair<bool, Technology::Identifier>> transitions = {
    578     {false, Technology::kEthernet},
    579     {true,  Technology::kPPPoE},
    580     {false, Technology::kEthernet},
    581   };
    582   for (const auto transition : transitions) {
    583     Error error;
    584     ethernet_->mutable_store()->SetBoolProperty(
    585         kPPPoEProperty, transition.first, &error);
    586     EXPECT_TRUE(error.IsSuccess());
    587     EXPECT_EQ(GetService()->technology(), transition.second);
    588   }
    589 }
    590 
    591 #else
    592 
    593 TEST_F(EthernetTest, PPPoEDisabled) {
    594   Error error;
    595   ethernet_->mutable_store()->SetBoolProperty(kPPPoEProperty, true, &error);
    596   EXPECT_FALSE(error.IsSuccess());
    597 }
    598 
    599 #endif  // DISABLE_PPPOE
    600 
    601 }  // namespace shill
    602