普通文本  |  443行  |  16.01 KB

//
// Copyright (C) 2014 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 "apmanager/config.h"

#include <string>

#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#if !defined(__ANDROID__)
#include <chromeos/dbus/service_constants.h>
#else
#include "dbus/apmanager/dbus-constants.h"
#endif

#include "apmanager/error.h"
#include "apmanager/fake_config_adaptor.h"
#include "apmanager/fake_device_adaptor.h"
#include "apmanager/mock_control.h"
#include "apmanager/mock_device.h"
#include "apmanager/mock_manager.h"

using ::testing::_;
using ::testing::Mock;
using ::testing::Return;
using ::testing::ReturnNew;
using ::testing::SetArgumentPointee;
namespace apmanager {

namespace {

const char kSsid[] = "TestSsid";
const char kInterface[] = "uap0";
const char kBridgeInterface[] = "br0";
const char kControlInterfacePath[] = "/var/run/apmanager/hostapd/ctrl_iface";
const char kPassphrase[] = "Passphrase";
const char k24GHzHTCapab[] = "[LDPC SMPS-STATIC GF SHORT-GI-20]";
const char k5GHzHTCapab[] =
    "[LDPC HT40+ SMPS-STATIC GF SHORT-GI-20 SHORT-GI-40]";

const uint16_t k24GHzChannel = 6;
const uint16_t k5GHzChannel = 36;

const char kExpected80211gConfigContent[] = "ssid=TestSsid\n"
                                            "channel=6\n"
                                            "interface=uap0\n"
                                            "hw_mode=g\n"
                                            "driver=nl80211\n"
                                            "fragm_threshold=2346\n"
                                            "rts_threshold=2347\n";

const char kExpected80211gBridgeConfigContent[] = "ssid=TestSsid\n"
                                                  "bridge=br0\n"
                                                  "channel=6\n"
                                                  "interface=uap0\n"
                                                  "hw_mode=g\n"
                                                  "driver=nl80211\n"
                                                  "fragm_threshold=2346\n"
                                                  "rts_threshold=2347\n";

const char kExpected80211gCtrlIfaceConfigContent[] =
    "ssid=TestSsid\n"
    "channel=6\n"
    "interface=uap0\n"
    "hw_mode=g\n"
    "ctrl_interface=/var/run/apmanager/hostapd/ctrl_iface\n"
#if !defined(__ANDROID__)
    "ctrl_interface_group=apmanager\n"
#else
    "ctrl_interface_group=system\n"
#endif  // __ANDROID__
    "driver=nl80211\n"
    "fragm_threshold=2346\n"
    "rts_threshold=2347\n";

const char kExpected80211n5GHzConfigContent[] =
    "ssid=TestSsid\n"
    "channel=36\n"
    "interface=uap0\n"
    "ieee80211n=1\n"
    "ht_capab=[LDPC HT40+ SMPS-STATIC GF SHORT-GI-20 SHORT-GI-40]\n"
    "hw_mode=a\n"
    "driver=nl80211\n"
    "fragm_threshold=2346\n"
    "rts_threshold=2347\n";

const char kExpected80211n24GHzConfigContent[] =
    "ssid=TestSsid\n"
    "channel=6\n"
    "interface=uap0\n"
    "ieee80211n=1\n"
    "ht_capab=[LDPC SMPS-STATIC GF SHORT-GI-20]\n"
    "hw_mode=g\n"
    "driver=nl80211\n"
    "fragm_threshold=2346\n"
    "rts_threshold=2347\n";

const char kExpectedRsnConfigContent[] = "ssid=TestSsid\n"
                                         "channel=6\n"
                                         "interface=uap0\n"
                                         "hw_mode=g\n"
                                         "wpa=2\n"
                                         "rsn_pairwise=CCMP\n"
                                         "wpa_key_mgmt=WPA-PSK\n"
                                         "wpa_passphrase=Passphrase\n"
                                         "driver=nl80211\n"
                                         "fragm_threshold=2346\n"
                                         "rts_threshold=2347\n";

}  // namespace

class ConfigTest : public testing::Test {
 public:
  ConfigTest()
      : manager_(&control_interface_) {
    ON_CALL(control_interface_, CreateDeviceAdaptorRaw())
        .WillByDefault(ReturnNew<FakeDeviceAdaptor>());
    ON_CALL(control_interface_, CreateConfigAdaptorRaw())
        .WillByDefault(ReturnNew<FakeConfigAdaptor>());
    // Defer creation of Config object to allow ControlInterface to setup
    // expectations for generating fake adaptors.
    config_.reset(new Config(&manager_, 0));
  }

  void SetupDevice(const std::string& interface) {
    // Setup mock device.
    device_ = new MockDevice(&manager_);
    device_->SetPreferredApInterface(interface);
    EXPECT_CALL(manager_, GetDeviceFromInterfaceName(interface))
        .WillRepeatedly(Return(device_));
  }

  void VerifyError(const Error& error,
                   Error::Type expected_type,
                   const std::string& expected_message_start) {
    EXPECT_EQ(expected_type, error.type());
    EXPECT_TRUE(base::StartsWith(error.message(), expected_message_start,
                                 base::CompareCase::INSENSITIVE_ASCII));
  }

 protected:
  MockControl control_interface_;
  MockManager manager_;
  scoped_refptr<MockDevice> device_;
  std::unique_ptr<Config> config_;
};

TEST_F(ConfigTest, GetFrequencyFromChannel) {
  uint32_t frequency;
  // Invalid channel.
  EXPECT_FALSE(Config::GetFrequencyFromChannel(0, &frequency));
  EXPECT_FALSE(Config::GetFrequencyFromChannel(166, &frequency));
  EXPECT_FALSE(Config::GetFrequencyFromChannel(14, &frequency));
  EXPECT_FALSE(Config::GetFrequencyFromChannel(33, &frequency));

  // Valid channel.
  const uint32_t kChannel1Frequency = 2412;
  const uint32_t kChannel13Frequency = 2472;
  const uint32_t kChannel34Frequency = 5170;
  const uint32_t kChannel165Frequency = 5825;
  EXPECT_TRUE(Config::GetFrequencyFromChannel(1, &frequency));
  EXPECT_EQ(kChannel1Frequency, frequency);
  EXPECT_TRUE(Config::GetFrequencyFromChannel(13, &frequency));
  EXPECT_EQ(kChannel13Frequency, frequency);
  EXPECT_TRUE(Config::GetFrequencyFromChannel(34, &frequency));
  EXPECT_EQ(kChannel34Frequency, frequency);
  EXPECT_TRUE(Config::GetFrequencyFromChannel(165, &frequency));
  EXPECT_EQ(kChannel165Frequency, frequency);
}

TEST_F(ConfigTest, ValidateSsid) {
  Error error;
  // SSID must contain between 1 and 32 characters.
  EXPECT_TRUE(config_->ValidateSsid(&error, "s"));
  EXPECT_TRUE(config_->ValidateSsid(&error, std::string(32, 'c')));
  EXPECT_FALSE(config_->ValidateSsid(&error, ""));
  EXPECT_FALSE(config_->ValidateSsid(&error, std::string(33, 'c')));
}

TEST_F(ConfigTest, ValidateSecurityMode) {
  Error error;
  EXPECT_TRUE(config_->ValidateSecurityMode(&error, kSecurityModeNone));
  EXPECT_TRUE(config_->ValidateSecurityMode(&error, kSecurityModeRSN));
  EXPECT_FALSE(config_->ValidateSecurityMode(&error, "InvalidSecurityMode"));
}

TEST_F(ConfigTest, ValidatePassphrase) {
  Error error;
  // Passpharse must contain between 8 and 63 characters.
  EXPECT_TRUE(config_->ValidatePassphrase(&error, std::string(8, 'c')));
  EXPECT_TRUE(config_->ValidatePassphrase(&error, std::string(63, 'c')));
  EXPECT_FALSE(config_->ValidatePassphrase(&error, std::string(7, 'c')));
  EXPECT_FALSE(config_->ValidatePassphrase(&error, std::string(64, 'c')));
}

TEST_F(ConfigTest, ValidateHwMode) {
  Error error;
  EXPECT_TRUE(config_->ValidateHwMode(&error, kHwMode80211a));
  EXPECT_TRUE(config_->ValidateHwMode(&error, kHwMode80211b));
  EXPECT_TRUE(config_->ValidateHwMode(&error, kHwMode80211g));
  EXPECT_TRUE(config_->ValidateHwMode(&error, kHwMode80211n));
  EXPECT_TRUE(config_->ValidateHwMode(&error, kHwMode80211ac));
  EXPECT_FALSE(config_->ValidateSecurityMode(&error, "InvalidHwMode"));
}

TEST_F(ConfigTest, ValidateOperationMode) {
  Error error;
  EXPECT_TRUE(config_->ValidateOperationMode(&error, kOperationModeServer));
  EXPECT_TRUE(config_->ValidateOperationMode(&error, kOperationModeBridge));
  EXPECT_FALSE(config_->ValidateOperationMode(&error, "InvalidMode"));
}

TEST_F(ConfigTest, ValidateChannel) {
  Error error;
  EXPECT_TRUE(config_->ValidateChannel(&error, 1));
  EXPECT_TRUE(config_->ValidateChannel(&error, 13));
  EXPECT_TRUE(config_->ValidateChannel(&error, 34));
  EXPECT_TRUE(config_->ValidateChannel(&error, 165));
  EXPECT_FALSE(config_->ValidateChannel(&error, 0));
  EXPECT_FALSE(config_->ValidateChannel(&error, 14));
  EXPECT_FALSE(config_->ValidateChannel(&error, 33));
  EXPECT_FALSE(config_->ValidateChannel(&error, 166));
}

TEST_F(ConfigTest, NoSsid) {
  config_->SetChannel(k24GHzChannel);
  config_->SetHwMode(kHwMode80211g);
  config_->SetInterfaceName(kInterface);

  std::string config_content;
  Error error;
  EXPECT_FALSE(config_->GenerateConfigFile(&error, &config_content));
  VerifyError(error, Error::kInvalidConfiguration, "SSID not specified");
}

TEST_F(ConfigTest, NoInterface) {
  // Basic 80211.g configuration.
  config_->SetSsid(kSsid);
  config_->SetChannel(k24GHzChannel);
  config_->SetHwMode(kHwMode80211g);

  // No device available, fail to generate config file.
  Error error;
  std::string config_content;
  EXPECT_CALL(manager_, GetAvailableDevice()).WillOnce(Return(nullptr));
  EXPECT_FALSE(config_->GenerateConfigFile(&error, &config_content));
  VerifyError(error, Error::kInternalError, "No device available");
  Mock::VerifyAndClearExpectations(&manager_);

  // Device available, config file should be generated without any problem.
  scoped_refptr<MockDevice> device = new MockDevice(&manager_);
  device->SetPreferredApInterface(kInterface);
  error.Reset();
  EXPECT_CALL(manager_, GetAvailableDevice()).WillOnce(Return(device));
  EXPECT_TRUE(config_->GenerateConfigFile(&error, &config_content));
  EXPECT_NE(std::string::npos, config_content.find(
                                   kExpected80211gConfigContent))
      << "Expected to find the following config...\n"
      << kExpected80211gConfigContent << "..within content...\n"
      << config_content;
  EXPECT_TRUE(error.IsSuccess());
  Mock::VerifyAndClearExpectations(&manager_);
}

TEST_F(ConfigTest, InvalidInterface) {
  // Basic 80211.g configuration.
  config_->SetSsid(kSsid);
  config_->SetChannel(k24GHzChannel);
  config_->SetHwMode(kHwMode80211g);
  config_->SetInterfaceName(kInterface);

  // Unable to find the device, fail to generate config file.
  Error error;
  std::string config_content;
  EXPECT_CALL(manager_, GetDeviceFromInterfaceName(kInterface))
      .WillOnce(Return(nullptr));
  EXPECT_FALSE(config_->GenerateConfigFile(&error, &config_content));
  VerifyError(error,
              Error::kInvalidConfiguration,
              "Unable to find device for the specified interface");
  Mock::VerifyAndClearExpectations(&manager_);
}

TEST_F(ConfigTest, BridgeMode) {
  config_->SetSsid(kSsid);
  config_->SetChannel(k24GHzChannel);
  config_->SetHwMode(kHwMode80211g);
  config_->SetInterfaceName(kInterface);
  config_->SetOperationMode(kOperationModeBridge);

  // Bridge interface required for bridge mode.
  Error error;
  std::string config_content;
  EXPECT_FALSE(config_->GenerateConfigFile(&error, &config_content));
  VerifyError(
      error, Error::kInvalidConfiguration, "Bridge interface not specified");

  // Set bridge interface, config file should be generated without error.
  config_->SetBridgeInterface(kBridgeInterface);
  // Setup mock device.
  SetupDevice(kInterface);
  error.Reset();
  std::string config_content1;
  EXPECT_TRUE(config_->GenerateConfigFile(&error, &config_content1));
  EXPECT_NE(std::string::npos, config_content1.find(
                                   kExpected80211gBridgeConfigContent))
      << "Expected to find the following config...\n"
      << kExpected80211gBridgeConfigContent << "..within content...\n"
      << config_content1;
  EXPECT_TRUE(error.IsSuccess());
}

TEST_F(ConfigTest, 80211gConfig) {
  config_->SetSsid(kSsid);
  config_->SetChannel(k24GHzChannel);
  config_->SetHwMode(kHwMode80211g);
  config_->SetInterfaceName(kInterface);

  // Setup mock device.
  SetupDevice(kInterface);

  std::string config_content;
  Error error;
  EXPECT_TRUE(config_->GenerateConfigFile(&error, &config_content));
  EXPECT_NE(std::string::npos, config_content.find(
                                   kExpected80211gConfigContent))
      << "Expected to find the following config...\n"
      << kExpected80211gConfigContent << "..within content...\n"
      << config_content;
  EXPECT_TRUE(error.IsSuccess());
}

TEST_F(ConfigTest, 80211gConfigWithControlInterface) {
  config_->SetSsid(kSsid);
  config_->SetChannel(k24GHzChannel);
  config_->SetHwMode(kHwMode80211g);
  config_->SetInterfaceName(kInterface);
  config_->set_control_interface(kControlInterfacePath);

  // Setup mock device.
  SetupDevice(kInterface);

  std::string config_content;
  Error error;
  EXPECT_TRUE(config_->GenerateConfigFile(&error, &config_content));
  EXPECT_NE(std::string::npos, config_content.find(
                                   kExpected80211gCtrlIfaceConfigContent))
      << "Expected to find the following config...\n"
      << kExpected80211gCtrlIfaceConfigContent << "..within content...\n"
      << config_content;
  EXPECT_TRUE(error.IsSuccess());
}

TEST_F(ConfigTest, 80211nConfig) {
  config_->SetSsid(kSsid);
  config_->SetHwMode(kHwMode80211n);
  config_->SetInterfaceName(kInterface);

  // Setup mock device.
  SetupDevice(kInterface);

  // 5GHz channel.
  config_->SetChannel(k5GHzChannel);
  std::string ghz5_config_content;
  Error error;
  std::string ht_capab_5ghz(k5GHzHTCapab);
  EXPECT_CALL(*device_.get(), GetHTCapability(k5GHzChannel, _))
      .WillOnce(DoAll(SetArgumentPointee<1>(ht_capab_5ghz), Return(true)));
  EXPECT_TRUE(config_->GenerateConfigFile(&error, &ghz5_config_content));
  EXPECT_NE(std::string::npos, ghz5_config_content.find(
                                   kExpected80211n5GHzConfigContent))
      << "Expected to find the following config...\n"
      << kExpected80211n5GHzConfigContent << "..within content...\n"
      << ghz5_config_content;
  EXPECT_TRUE(error.IsSuccess());
  Mock::VerifyAndClearExpectations(device_.get());

  // 2.4GHz channel.
  config_->SetChannel(k24GHzChannel);
  std::string ghz24_config_content;
  error.Reset();
  std::string ht_capab_24ghz(k24GHzHTCapab);
  EXPECT_CALL(*device_.get(), GetHTCapability(k24GHzChannel, _))
      .WillOnce(DoAll(SetArgumentPointee<1>(ht_capab_24ghz), Return(true)));
  EXPECT_TRUE(config_->GenerateConfigFile(&error, &ghz24_config_content));
  EXPECT_NE(std::string::npos, ghz24_config_content.find(
                                   kExpected80211n24GHzConfigContent))
      << "Expected to find the following config...\n"
      << kExpected80211n24GHzConfigContent << "..within content...\n"
      << ghz24_config_content;
  EXPECT_TRUE(error.IsSuccess());
  Mock::VerifyAndClearExpectations(device_.get());
}

TEST_F(ConfigTest, RsnConfig) {
  config_->SetSsid(kSsid);
  config_->SetChannel(k24GHzChannel);
  config_->SetHwMode(kHwMode80211g);
  config_->SetInterfaceName(kInterface);
  config_->SetSecurityMode(kSecurityModeRSN);

  // Setup mock device.
  SetupDevice(kInterface);

  // Failed due to no passphrase specified.
  std::string config_content;
  Error error;
  EXPECT_FALSE(config_->GenerateConfigFile(&error, &config_content));
  VerifyError(
      error,
      Error::kInvalidConfiguration,
      base::StringPrintf("Passphrase not set for security mode: %s",
                         kSecurityModeRSN));

  error.Reset();
  config_->SetPassphrase(kPassphrase);
  EXPECT_TRUE(config_->GenerateConfigFile(&error, &config_content));
  EXPECT_NE(std::string::npos, config_content.find(
                                   kExpectedRsnConfigContent))
      << "Expected to find the following config...\n"
      << kExpectedRsnConfigContent << "..within content...\n"
      << config_content;
  EXPECT_TRUE(error.IsSuccess());
}

}  // namespace apmanager