普通文本  |  254行  |  8.71 KB

//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "shill/wifi/tdls_manager.h"

#include <map>
#include <string>

#if defined(__ANDROID__)
#include <dbus/service_constants.h>
#else
#include <chromeos/dbus/service_constants.h>
#endif  // __ANDROID__
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "shill/error.h"
#include "shill/mock_event_dispatcher.h"
#include "shill/supplicant/mock_supplicant_interface_proxy.h"
#include "shill/supplicant/wpa_supplicant.h"

using std::string;
using std::vector;
using ::testing::_;
using ::testing::Mock;
using ::testing::Return;
using ::testing::SetArgumentPointee;
using ::testing::StrEq;
using ::testing::StrictMock;

namespace shill {

class TDLSManagerTest : public testing::Test {
 public:
  TDLSManagerTest()
      : tdls_manager_(&event_dispatcher_, &supplicant_interface_proxy_, "") {}

  void SetPeerDiscovering(const string& peer_mac_address) {
    tdls_manager_.peer_discovery_state_[peer_mac_address] =
        TDLSManager::PeerDiscoveryState::kRequestSent;
  }
  bool IsPeerDiscovering(const string& peer_mac_address) {
    return tdls_manager_.CheckDiscoveryState(peer_mac_address) ==
        TDLSManager::PeerDiscoveryState::kRequestSent;
  }

  void SetPeerDiscovered(const string& peer_mac_address) {
    tdls_manager_.peer_discovery_state_[peer_mac_address] =
        TDLSManager::PeerDiscoveryState::kResponseReceived;
  }
  bool IsPeerDiscovered(const string& peer_mac_address) {
    return tdls_manager_.CheckDiscoveryState(peer_mac_address) ==
        TDLSManager::PeerDiscoveryState::kResponseReceived;
  }

  bool IsPeerDiscoveryCleanupTimerSetup() {
    return !tdls_manager_.peer_discovery_cleanup_callback_.IsCancelled();
  }

  void OnPeerDiscoveryCleanup() {
    return tdls_manager_.PeerDiscoveryCleanup();
  }

 protected:
  StrictMock<MockEventDispatcher> event_dispatcher_;
  StrictMock<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
  TDLSManager tdls_manager_;
};

TEST_F(TDLSManagerTest, DiscoverPeer) {
  const char kPeer[] = "peer";
  Error error;

  EXPECT_FALSE(IsPeerDiscovering(kPeer));
  EXPECT_FALSE(IsPeerDiscoveryCleanupTimerSetup());

  // TDLS discover operation succeed.
  EXPECT_CALL(supplicant_interface_proxy_, TDLSDiscover(StrEq(kPeer)))
      .WillOnce(Return(true));
  // Post delayed task for discover peer cleanup timer.
  EXPECT_CALL(event_dispatcher_, PostDelayedTask(_, _)).Times(1);
  EXPECT_EQ("",
            tdls_manager_.PerformOperation(
                kPeer, kTDLSDiscoverOperation, &error));
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_TRUE(IsPeerDiscovering(kPeer));
  EXPECT_TRUE(IsPeerDiscoveryCleanupTimerSetup());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
  Mock::VerifyAndClearExpectations(&event_dispatcher_);

  // TDLS discover operation failed.
  error.Reset();
  EXPECT_CALL(supplicant_interface_proxy_, TDLSDiscover(StrEq(kPeer)))
      .WillOnce(Return(false));
  EXPECT_CALL(event_dispatcher_, PostDelayedTask(_, _)).Times(0);
  EXPECT_EQ("",
            tdls_manager_.PerformOperation(
                kPeer, kTDLSDiscoverOperation, &error));
  EXPECT_EQ(Error::kOperationFailed, error.type());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
  Mock::VerifyAndClearExpectations(&event_dispatcher_);
}

TEST_F(TDLSManagerTest, SetupPeer) {
  const char kPeer[] = "peer";
  Error error;

  // TDLS setup operation succeed.
  EXPECT_CALL(supplicant_interface_proxy_, TDLSSetup(StrEq(kPeer)))
      .WillOnce(Return(true));
  EXPECT_EQ("",
            tdls_manager_.PerformOperation(
                kPeer, kTDLSSetupOperation, &error));
  EXPECT_TRUE(error.IsSuccess());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);

  // TDLS setup operation failed.
  error.Reset();
  EXPECT_CALL(supplicant_interface_proxy_, TDLSSetup(StrEq(kPeer)))
      .WillOnce(Return(false));
  EXPECT_EQ("",
            tdls_manager_.PerformOperation(
                kPeer, kTDLSSetupOperation, &error));
  EXPECT_EQ(Error::kOperationFailed, error.type());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
}

TEST_F(TDLSManagerTest, TeardownPeer) {
  const char kPeer[] = "peer";
  Error error;

  // TDLS teardown operation succeed.
  EXPECT_CALL(supplicant_interface_proxy_, TDLSTeardown(StrEq(kPeer)))
      .WillOnce(Return(true));
  EXPECT_EQ("",
            tdls_manager_.PerformOperation(
                kPeer, kTDLSTeardownOperation, &error));
  EXPECT_TRUE(error.IsSuccess());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);

  // TDLS teardown operation failed.
  error.Reset();
  EXPECT_CALL(supplicant_interface_proxy_, TDLSTeardown(StrEq(kPeer)))
      .WillOnce(Return(false));
  EXPECT_EQ("",
            tdls_manager_.PerformOperation(
                kPeer, kTDLSTeardownOperation, &error));
  EXPECT_EQ(Error::kOperationFailed, error.type());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
}

TEST_F(TDLSManagerTest, PeerStatus) {
  const char kPeer[] = "peer";
  Error error;

  // TDLS status operation succeed.
  const std::map<string, string> kTDLSStatusMap {
    { "Baby, I don't care", kTDLSUnknownState },
    { WPASupplicant::kTDLSStateConnected, kTDLSConnectedState },
    { WPASupplicant::kTDLSStateDisabled, kTDLSDisabledState },
    { WPASupplicant::kTDLSStatePeerDoesNotExist, kTDLSNonexistentState },
    { WPASupplicant::kTDLSStatePeerNotConnected, kTDLSDisconnectedState },
  };
  for (const auto& it : kTDLSStatusMap) {
    error.Reset();
    EXPECT_CALL(supplicant_interface_proxy_, TDLSStatus(StrEq(kPeer), _))
        .WillOnce(DoAll(SetArgumentPointee<1>(it.first), Return(true)));
    EXPECT_EQ(it.second,
              tdls_manager_.PerformOperation(
                  kPeer, kTDLSStatusOperation, &error));
    EXPECT_TRUE(error.IsSuccess());
    Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
  }

  // Discovered Peer in non-existent state should return "Disconnected" state.
  error.Reset();
  SetPeerDiscovered(kPeer);
  EXPECT_CALL(supplicant_interface_proxy_, TDLSStatus(StrEq(kPeer), _))
      .WillOnce(
          DoAll(SetArgumentPointee<1>(
                    string(WPASupplicant::kTDLSStatePeerDoesNotExist)),
                Return(true)));
  EXPECT_EQ(kTDLSDisconnectedState,
            tdls_manager_.PerformOperation(
                kPeer, kTDLSStatusOperation, &error));
  EXPECT_TRUE(error.IsSuccess());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);

  // TDLS status operation failed.
  error.Reset();
  EXPECT_CALL(supplicant_interface_proxy_, TDLSStatus(StrEq(kPeer), _))
      .WillOnce(Return(false));
  EXPECT_EQ("",
            tdls_manager_.PerformOperation(
                kPeer, kTDLSStatusOperation, &error));
  EXPECT_EQ(Error::kOperationFailed, error.type());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
}

TEST_F(TDLSManagerTest, OnDiscoverResponseReceived) {
  const char kPeer[] = "peer";

  // Received discover response for a peer without discover request.
  EXPECT_FALSE(IsPeerDiscovering(kPeer));
  EXPECT_FALSE(IsPeerDiscovered(kPeer));
  tdls_manager_.OnDiscoverResponseReceived(kPeer);
  EXPECT_FALSE(IsPeerDiscovering(kPeer));
  EXPECT_FALSE(IsPeerDiscovered(kPeer));

  // Receive discover response for a peer with discover request.
  SetPeerDiscovering(kPeer);
  EXPECT_TRUE(IsPeerDiscovering(kPeer));
  tdls_manager_.OnDiscoverResponseReceived(kPeer);
  EXPECT_TRUE(IsPeerDiscovered(kPeer));
}

TEST_F(TDLSManagerTest, PeerDiscoveryCleanup) {
  const char kPeer[] = "peer";

  // Start TDLS discover for a peer |kPeer|.
  Error error;
  EXPECT_CALL(supplicant_interface_proxy_, TDLSDiscover(StrEq(kPeer)))
      .WillOnce(Return(true));
  // Post delayed task for discover peer cleanup timer.
  EXPECT_CALL(event_dispatcher_, PostDelayedTask(_, _)).Times(1);
  EXPECT_EQ("",
            tdls_manager_.PerformOperation(
                kPeer, kTDLSDiscoverOperation, &error));
  EXPECT_TRUE(error.IsSuccess());
  EXPECT_TRUE(IsPeerDiscovering(kPeer));
  EXPECT_TRUE(IsPeerDiscoveryCleanupTimerSetup());
  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
  Mock::VerifyAndClearExpectations(&event_dispatcher_);

  // Peer discovery cleanup.
  OnPeerDiscoveryCleanup();
  EXPECT_FALSE(IsPeerDiscovering(kPeer));
}

}  // namespace shill