chromium/chromeos/ash/components/network/device_state_unittest.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ash/components/network/device_state.h"

#include "base/test/task_environment.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/network_state_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"

namespace ash {
namespace {

const char kTestCellularDevicePath[] = "cellular_path";
const char kTestCellularDeviceName[] = "cellular_name";
const char kTestCellularPSimIccid[] = "psim_iccid";
const char kTestCellularESimIccid[] = "esim_iccid";
const char kTestCellularEid[] = "eid";

const char kTestWifiDevicePath[] = "wifi_path";
const char kTestWifiDeviceName[] = "wifi_name";
const char kTestIpv6ConfigPath[] = "/ipconfig/wlan0_ipv6";
const char kTestIpv4ConfigPath[] = "/ipconfig/wlan0_ipv4";
const char kTestIpv4Address_1[] = "192.168.1.255";
const char kTestIpv4Address_2[] = "192.168.1.123";
const char kTestIpv6Address_1[] = "2600:1700:6900:f000:ab00:8a39:2099:72fd";
const char kTestIpv6Address_2[] = "2600:1700:6900:f000:ab00:8a39:2099:12df";

// Creates a list of cellular SIM slots with an eSIM and pSIM slot.
base::Value GenerateTestSimSlotInfos() {
  auto psim_slot_info =
      base::Value::Dict()
          .Set(shill::kSIMSlotInfoICCID, kTestCellularPSimIccid)
          .Set(shill::kSIMSlotInfoEID, std::string())
          .Set(shill::kSIMSlotInfoPrimary, true);

  auto esim_slot_info =
      base::Value::Dict()
          .Set(shill::kSIMSlotInfoICCID, kTestCellularESimIccid)
          .Set(shill::kSIMSlotInfoEID, kTestCellularEid)
          .Set(shill::kSIMSlotInfoPrimary, false);

  auto sim_slot_infos = base::Value::List()
                            .Append(std::move(psim_slot_info))
                            .Append(std::move(esim_slot_info));

  return base::Value(std::move(sim_slot_infos));
}

}  // namespace

class DeviceStateTest : public testing::Test {
 protected:
  DeviceStateTest() = default;
  DeviceStateTest(const DeviceStateTest&) = delete;
  DeviceStateTest& operator=(const DeviceStateTest&) = delete;
  ~DeviceStateTest() override = default;

  // testing::Test:
  void SetUp() override {
    helper_.device_test()->AddDevice(
        kTestCellularDevicePath, shill::kTypeCellular, kTestCellularDeviceName);
    helper_.device_test()->AddDevice(kTestWifiDevicePath, shill::kTypeWifi,
                                     kTestWifiDeviceName);
    base::RunLoop().RunUntilIdle();
  }

  const DeviceState* GetCellularDevice() {
    return helper_.network_state_handler()->GetDeviceState(
        kTestCellularDevicePath);
  }

  const DeviceState* GetWifiDevice() {
    return helper_.network_state_handler()->GetDeviceState(kTestWifiDevicePath);
  }

  void UpdateDeviceIpConfigProperties(const std::string& device_path,
                                      const std::string& ip_config_path,
                                      base::Value::Dict properties) {
    helper_.network_state_handler()->UpdateIPConfigProperties(
        ManagedState::MANAGED_TYPE_DEVICE, device_path, ip_config_path,
        std::move(properties));
  }

  void SetIccid() {
    helper_.device_test()->SetDeviceProperty(
        kTestCellularDevicePath, shill::kIccidProperty,
        base::Value(kTestCellularPSimIccid), /*notify_changed=*/true);
    base::RunLoop().RunUntilIdle();
  }

  void SetFlashing(bool flashing) {
    helper_.device_test()->SetDeviceProperty(
        kTestCellularDevicePath, shill::kFlashingProperty,
        base::Value(flashing), /*notify_changed=*/true);
    base::RunLoop().RunUntilIdle();
  }

  void SetSimSlotInfos() {
    helper_.device_test()->SetDeviceProperty(
        kTestCellularDevicePath, shill::kSIMSlotInfoProperty,
        GenerateTestSimSlotInfos(), /*notify_changed=*/true);
    base::RunLoop().RunUntilIdle();
  }

 private:
  base::test::SingleThreadTaskEnvironment task_environment_;
  NetworkStateTestHelper helper_{/*use_default_devices_and_services=*/false};
};

TEST_F(DeviceStateTest, SimSlotInfo_Cellular) {
  // Set an ICCID, but do not set the SIMSlotInfo property.
  SetIccid();

  // A single SIM slot should have been created, copying the ICCID.
  DeviceState::CellularSIMSlotInfos infos =
      GetCellularDevice()->GetSimSlotInfos();
  EXPECT_EQ(1u, infos.size());
  EXPECT_EQ(kTestCellularPSimIccid, infos[0].iccid);
  EXPECT_TRUE(infos[0].eid.empty());
  EXPECT_TRUE(infos[0].primary);

  // Set the SIM Slot infos.
  SetSimSlotInfos();
  infos = GetCellularDevice()->GetSimSlotInfos();
  EXPECT_EQ(2u, infos.size());
  EXPECT_EQ(kTestCellularPSimIccid, infos[0].iccid);
  EXPECT_TRUE(infos[0].eid.empty());
  EXPECT_TRUE(infos[0].primary);
  EXPECT_EQ(kTestCellularESimIccid, infos[1].iccid);
  EXPECT_EQ(kTestCellularEid, infos[1].eid);
  EXPECT_FALSE(infos[1].primary);
}

TEST_F(DeviceStateTest, Flashing_Cellular) {
  SetFlashing(true);
  EXPECT_TRUE(GetCellularDevice()->flashing());
  SetFlashing(false);
  EXPECT_FALSE(GetCellularDevice()->flashing());
}

TEST_F(DeviceStateTest, SimSlotInfo_Wifi) {
  // Default SIM slots should not be created for non-cellular.
  EXPECT_TRUE(GetWifiDevice()->GetSimSlotInfos().empty());
}

TEST_F(DeviceStateTest, DeviceIPAddress) {
  auto dhcp_ip_config = base::Value::Dict()
                            .Set(shill::kAddressProperty, kTestIpv4Address_1)
                            .Set(shill::kMethodProperty, shill::kTypeDHCP);
  UpdateDeviceIpConfigProperties(kTestWifiDevicePath, kTestIpv4ConfigPath,
                                 std::move(dhcp_ip_config));
  EXPECT_EQ(kTestIpv4Address_1,
            GetWifiDevice()->GetIpAddressByType(shill::kTypeIPv4));
  EXPECT_EQ(std::string(),
            GetWifiDevice()->GetIpAddressByType(shill::kTypeIPv6));

  auto ipv4_ip_config = base::Value::Dict()
                            .Set(shill::kAddressProperty, kTestIpv4Address_2)
                            .Set(shill::kMethodProperty, shill::kTypeIPv4);
  UpdateDeviceIpConfigProperties(kTestWifiDevicePath, kTestIpv4ConfigPath,
                                 std::move(ipv4_ip_config));
  EXPECT_EQ(kTestIpv4Address_2,
            GetWifiDevice()->GetIpAddressByType(shill::kTypeIPv4));
  EXPECT_EQ(std::string(),
            GetWifiDevice()->GetIpAddressByType(shill::kTypeIPv6));

  auto slaac_ip_config = base::Value::Dict()
                             .Set(shill::kAddressProperty, kTestIpv6Address_1)
                             .Set(shill::kMethodProperty, shill::kTypeSLAAC);
  UpdateDeviceIpConfigProperties(kTestWifiDevicePath, kTestIpv6ConfigPath,
                                 std::move(slaac_ip_config));
  EXPECT_EQ(kTestIpv4Address_2,
            GetWifiDevice()->GetIpAddressByType(shill::kTypeIPv4));
  EXPECT_EQ(kTestIpv6Address_1,
            GetWifiDevice()->GetIpAddressByType(shill::kTypeIPv6));

  auto ipv6_ip_config = base::Value::Dict()
                            .Set(shill::kAddressProperty, kTestIpv6Address_2)
                            .Set(shill::kMethodProperty, shill::kTypeIPv6);
  UpdateDeviceIpConfigProperties(kTestWifiDevicePath, kTestIpv6ConfigPath,
                                 std::move(ipv6_ip_config));
  EXPECT_EQ(kTestIpv4Address_2,
            GetWifiDevice()->GetIpAddressByType(shill::kTypeIPv4));
  EXPECT_EQ(kTestIpv6Address_2,
            GetWifiDevice()->GetIpAddressByType(shill::kTypeIPv6));
}

}  // namespace ash