//
// Copyright (C) 2012 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 "update_engine/connection_manager.h"

#include <set>
#include <string>

#include <base/logging.h>
#include <brillo/any.h>
#include <brillo/message_loops/fake_message_loop.h>
#include <brillo/variant_dictionary.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <shill/dbus-constants.h>
#include <shill/dbus-proxies.h>
#include <shill/dbus-proxy-mocks.h>

#include "update_engine/common/test_utils.h"
#include "update_engine/fake_shill_proxy.h"
#include "update_engine/fake_system_state.h"

using chromeos_update_engine::connection_utils::StringForConnectionType;
using org::chromium::flimflam::ManagerProxyMock;
using org::chromium::flimflam::ServiceProxyMock;
using std::set;
using std::string;
using testing::Return;
using testing::SetArgPointee;
using testing::_;

namespace chromeos_update_engine {

class ConnectionManagerTest : public ::testing::Test {
 public:
  ConnectionManagerTest() : fake_shill_proxy_(new FakeShillProxy()) {}

  void SetUp() override {
    loop_.SetAsCurrent();
    fake_system_state_.set_connection_manager(&cmut_);
  }

  void TearDown() override { EXPECT_FALSE(loop_.PendingTasks()); }

 protected:
  // Sets the default_service object path in the response from the
  // ManagerProxyMock instance.
  void SetManagerReply(const char* default_service, bool reply_succeeds);

  // Sets the |service_type|, |physical_technology| and |service_tethering|
  // properties in the mocked service |service_path|. If any of the three
  // const char* is a nullptr, the corresponding property will not be included
  // in the response.
  void SetServiceReply(const string& service_path,
                       const char* service_type,
                       const char* physical_technology,
                       const char* service_tethering);

  void TestWithServiceType(
      const char* service_type,
      const char* physical_technology,
      ConnectionType expected_type);
  void TestWithServiceTethering(
      const char* service_tethering,
      ConnectionTethering expected_tethering);

  brillo::FakeMessageLoop loop_{nullptr};
  FakeSystemState fake_system_state_;
  FakeShillProxy* fake_shill_proxy_;

  // ConnectionManager under test.
  ConnectionManager cmut_{fake_shill_proxy_, &fake_system_state_};
};

void ConnectionManagerTest::SetManagerReply(const char* default_service,
                                            bool reply_succeeds) {
  ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_->GetManagerProxy();
  if (!reply_succeeds) {
    EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _))
        .WillOnce(Return(false));
    return;
  }

  // Create a dictionary of properties and optionally include the default
  // service.
  brillo::VariantDictionary reply_dict;
  reply_dict["SomeOtherProperty"] = 0xC0FFEE;

  if (default_service) {
    reply_dict[shill::kDefaultServiceProperty] =
        dbus::ObjectPath(default_service);
  }
  EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _))
      .WillOnce(DoAll(SetArgPointee<0>(reply_dict), Return(true)));
}

void ConnectionManagerTest::SetServiceReply(const string& service_path,
                                            const char* service_type,
                                            const char* physical_technology,
                                            const char* service_tethering) {
  brillo::VariantDictionary reply_dict;
  reply_dict["SomeOtherProperty"] = 0xC0FFEE;

  if (service_type)
    reply_dict[shill::kTypeProperty] = string(service_type);

  if (physical_technology) {
    reply_dict[shill::kPhysicalTechnologyProperty] =
        string(physical_technology);
  }

  if (service_tethering)
    reply_dict[shill::kTetheringProperty] = string(service_tethering);

  std::unique_ptr<ServiceProxyMock> service_proxy_mock(new ServiceProxyMock());

  // Plumb return value into mock object.
  EXPECT_CALL(*service_proxy_mock.get(), GetProperties(_, _, _))
      .WillOnce(DoAll(SetArgPointee<0>(reply_dict), Return(true)));

  fake_shill_proxy_->SetServiceForPath(dbus::ObjectPath(service_path),
                                       std::move(service_proxy_mock));
}

void ConnectionManagerTest::TestWithServiceType(
    const char* service_type,
    const char* physical_technology,
    ConnectionType expected_type) {
  SetManagerReply("/service/guest/network", true);
  SetServiceReply("/service/guest/network",
                  service_type,
                  physical_technology,
                  shill::kTetheringNotDetectedState);

  ConnectionType type;
  ConnectionTethering tethering;
  EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering));
  EXPECT_EQ(expected_type, type);
  testing::Mock::VerifyAndClearExpectations(
      fake_shill_proxy_->GetManagerProxy());
}

void ConnectionManagerTest::TestWithServiceTethering(
    const char* service_tethering,
    ConnectionTethering expected_tethering) {
  SetManagerReply("/service/guest/network", true);
  SetServiceReply(
      "/service/guest/network", shill::kTypeWifi, nullptr, service_tethering);

  ConnectionType type;
  ConnectionTethering tethering;
  EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering));
  EXPECT_EQ(expected_tethering, tethering);
  testing::Mock::VerifyAndClearExpectations(
      fake_shill_proxy_->GetManagerProxy());
}

TEST_F(ConnectionManagerTest, SimpleTest) {
  TestWithServiceType(shill::kTypeEthernet, nullptr, ConnectionType::kEthernet);
  TestWithServiceType(shill::kTypeWifi, nullptr, ConnectionType::kWifi);
  TestWithServiceType(shill::kTypeWimax, nullptr, ConnectionType::kWimax);
  TestWithServiceType(
      shill::kTypeBluetooth, nullptr, ConnectionType::kBluetooth);
  TestWithServiceType(shill::kTypeCellular, nullptr, ConnectionType::kCellular);
}

TEST_F(ConnectionManagerTest, PhysicalTechnologyTest) {
  TestWithServiceType(shill::kTypeVPN, nullptr, ConnectionType::kUnknown);
  TestWithServiceType(
      shill::kTypeVPN, shill::kTypeVPN, ConnectionType::kUnknown);
  TestWithServiceType(shill::kTypeVPN, shill::kTypeWifi, ConnectionType::kWifi);
  TestWithServiceType(
      shill::kTypeVPN, shill::kTypeWimax, ConnectionType::kWimax);
}

TEST_F(ConnectionManagerTest, TetheringTest) {
  TestWithServiceTethering(shill::kTetheringConfirmedState,
                           ConnectionTethering::kConfirmed);
  TestWithServiceTethering(shill::kTetheringNotDetectedState,
                           ConnectionTethering::kNotDetected);
  TestWithServiceTethering(shill::kTetheringSuspectedState,
                           ConnectionTethering::kSuspected);
  TestWithServiceTethering("I'm not a valid property value =)",
                           ConnectionTethering::kUnknown);
}

TEST_F(ConnectionManagerTest, UnknownTest) {
  TestWithServiceType("foo", nullptr, ConnectionType::kUnknown);
}

TEST_F(ConnectionManagerTest, AllowUpdatesOverEthernetTest) {
  // Updates over Ethernet are allowed even if there's no policy.
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
                                        ConnectionTethering::kUnknown));
}

TEST_F(ConnectionManagerTest, AllowUpdatesOverWifiTest) {
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
                                        ConnectionTethering::kUnknown));
}

TEST_F(ConnectionManagerTest, AllowUpdatesOverWimaxTest) {
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWimax,
                                        ConnectionTethering::kUnknown));
}

TEST_F(ConnectionManagerTest, BlockUpdatesOverBluetoothTest) {
  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kBluetooth,
                                         ConnectionTethering::kUnknown));
}

TEST_F(ConnectionManagerTest, AllowUpdatesOnlyOver3GPerPolicyTest) {
  policy::MockDevicePolicy allow_3g_policy;

  fake_system_state_.set_device_policy(&allow_3g_policy);

  // This test tests cellular (3G) being the only connection type being allowed.
  set<string> allowed_set;
  allowed_set.insert(StringForConnectionType(ConnectionType::kCellular));

  EXPECT_CALL(allow_3g_policy, GetAllowedConnectionTypesForUpdate(_))
      .Times(1)
      .WillOnce(DoAll(SetArgPointee<0>(allowed_set), Return(true)));

  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
                                        ConnectionTethering::kUnknown));
}

TEST_F(ConnectionManagerTest, AllowUpdatesOver3GAndOtherTypesPerPolicyTest) {
  policy::MockDevicePolicy allow_3g_policy;

  fake_system_state_.set_device_policy(&allow_3g_policy);

  // This test tests multiple connection types being allowed, with
  // 3G one among them. Only Cellular is currently enforced by the policy
  // setting, the others are ignored (see Bluetooth for example).
  set<string> allowed_set;
  allowed_set.insert(StringForConnectionType(ConnectionType::kCellular));
  allowed_set.insert(StringForConnectionType(ConnectionType::kBluetooth));

  EXPECT_CALL(allow_3g_policy, GetAllowedConnectionTypesForUpdate(_))
      .Times(3)
      .WillRepeatedly(DoAll(SetArgPointee<0>(allowed_set), Return(true)));

  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
                                        ConnectionTethering::kUnknown));
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
                                        ConnectionTethering::kNotDetected));
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
                                        ConnectionTethering::kUnknown));
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
                                        ConnectionTethering::kUnknown));
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWimax,
                                        ConnectionTethering::kUnknown));
  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kBluetooth,
                                         ConnectionTethering::kUnknown));

  // Tethered networks are treated in the same way as Cellular networks and
  // thus allowed.
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
                                        ConnectionTethering::kConfirmed));
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
                                        ConnectionTethering::kConfirmed));
}

TEST_F(ConnectionManagerTest, AllowUpdatesOverCellularByDefaultTest) {
  policy::MockDevicePolicy device_policy;
  // Set an empty device policy.
  fake_system_state_.set_device_policy(&device_policy);

  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
                                        ConnectionTethering::kUnknown));
}

TEST_F(ConnectionManagerTest, AllowUpdatesOverTetheredNetworkByDefaultTest) {
  policy::MockDevicePolicy device_policy;
  // Set an empty device policy.
  fake_system_state_.set_device_policy(&device_policy);

  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
                                        ConnectionTethering::kConfirmed));
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
                                        ConnectionTethering::kConfirmed));
  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
                                        ConnectionTethering::kSuspected));
}

TEST_F(ConnectionManagerTest, BlockUpdatesOver3GPerPolicyTest) {
  policy::MockDevicePolicy block_3g_policy;

  fake_system_state_.set_device_policy(&block_3g_policy);

  // Test that updates for 3G are blocked while updates are allowed
  // over several other types.
  set<string> allowed_set;
  allowed_set.insert(StringForConnectionType(ConnectionType::kEthernet));
  allowed_set.insert(StringForConnectionType(ConnectionType::kWifi));
  allowed_set.insert(StringForConnectionType(ConnectionType::kWimax));

  EXPECT_CALL(block_3g_policy, GetAllowedConnectionTypesForUpdate(_))
      .Times(1)
      .WillOnce(DoAll(SetArgPointee<0>(allowed_set), Return(true)));

  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
                                         ConnectionTethering::kUnknown));
}

TEST_F(ConnectionManagerTest, AllowUpdatesOver3GIfPolicyIsNotSet) {
  policy::MockDevicePolicy device_policy;

  fake_system_state_.set_device_policy(&device_policy);

  // Return false for GetAllowedConnectionTypesForUpdate and see
  // that updates are allowed as device policy is not set. Further
  // check is left to |OmahaRequestAction|.
  EXPECT_CALL(device_policy, GetAllowedConnectionTypesForUpdate(_))
      .Times(1)
      .WillOnce(Return(false));

  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
                                        ConnectionTethering::kUnknown));
}

TEST_F(ConnectionManagerTest, StringForConnectionTypeTest) {
  EXPECT_STREQ(shill::kTypeEthernet,
               StringForConnectionType(ConnectionType::kEthernet));
  EXPECT_STREQ(shill::kTypeWifi,
               StringForConnectionType(ConnectionType::kWifi));
  EXPECT_STREQ(shill::kTypeWimax,
               StringForConnectionType(ConnectionType::kWimax));
  EXPECT_STREQ(shill::kTypeBluetooth,
               StringForConnectionType(ConnectionType::kBluetooth));
  EXPECT_STREQ(shill::kTypeCellular,
               StringForConnectionType(ConnectionType::kCellular));
  EXPECT_STREQ("Unknown", StringForConnectionType(ConnectionType::kUnknown));
  EXPECT_STREQ("Unknown",
               StringForConnectionType(static_cast<ConnectionType>(999999)));
}

TEST_F(ConnectionManagerTest, MalformedServiceList) {
  SetManagerReply("/service/guest/network", false);

  ConnectionType type;
  ConnectionTethering tethering;
  EXPECT_FALSE(cmut_.GetConnectionProperties(&type, &tethering));
}

}  // namespace chromeos_update_engine
