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

// Copyright 2023 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/network_3gpp_handler.h"

#include <memory>
#include <set>
#include <string>

#include "ash/constants/ash_features.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "chromeos/ash/components/dbus/shill/fake_modem_3gpp_client.h"
#include "chromeos/ash/components/dbus/shill/modem_3gpp_client.h"
#include "chromeos/ash/components/dbus/shill/shill_clients.h"
#include "chromeos/ash/components/dbus/shill/shill_device_client.h"
#include "chromeos/dbus/constants/dbus_switches.h"
#include "dbus/object_path.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace ash {

namespace {

const char kCellularDevicePath[] = "/org/freedesktop/ModemManager1/stub/0";
const char kCellularDeviceObjectPath[] =
    "/org/freedesktop/ModemManager1/stub/0/Modem/1";
const char kCellularDeviceConfiguration[] = "carrier.lock.configuration";

}  // namespace

class Network3gppHandlerTest : public testing::Test {
 public:
  Network3gppHandlerTest()
      : task_environment_(
            base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {}
  ~Network3gppHandlerTest() override = default;

  void SetUp() override {
    // Initialize fake clients.
    shill_clients::InitializeFakes();
    device_test_ = ShillDeviceClient::Get()->GetTestInterface();
    ASSERT_TRUE(device_test_);

    // We want to have only 1 cellular device.
    device_test_->ClearDevices();
    device_test_->AddDevice(kCellularDevicePath, shill::kTypeCellular,
                            "stub_cellular_device");

    // This relies on the stub dbus implementations for ShillManagerClient,
    // ShillDeviceClient, Modem3gppClient.
    network_3gpp_handler_ = std::make_unique<Network3gppHandler>();
    network_3gpp_handler_->Init();
    base::RunLoop().RunUntilIdle();
    modem_fake_client_ =
        static_cast<FakeModem3gppClient*>(network_3gpp_handler_->modem_client_);
  }

  void TearDown() override {
    device_test_ = nullptr;
    modem_fake_client_ = nullptr;
    network_3gpp_handler_.reset();
    shill_clients::Shutdown();
  }

 protected:
  base::test::SingleThreadTaskEnvironment task_environment_;
  raw_ptr<ShillDeviceClient::TestInterface> device_test_;
  raw_ptr<FakeModem3gppClient> modem_fake_client_;
  std::unique_ptr<Network3gppHandler> network_3gpp_handler_;
  base::test::ScopedFeatureList scoped_feature_list_;
};

TEST_F(Network3gppHandlerTest, EmptyDbusObjectPath) {
  // This test verifies no crash occurs when the device dbus object path
  // is an empty value.
  device_test_->SetDeviceProperty(kCellularDevicePath,
                                  shill::kDBusObjectProperty, base::Value(""),
                                  /*notify_changed=*/true);

  base::RunLoop().RunUntilIdle();
}

TEST_F(Network3gppHandlerTest, SwapDbusObjectPath) {
  // This test verifies no crash occurs when the device object
  // path is changed multiple times.
  device_test_->SetDeviceProperty(kCellularDevicePath,
                                  shill::kDBusObjectProperty, base::Value(""),
                                  /*notify_changed=*/true);
  device_test_->SetDeviceProperty(kCellularDevicePath,
                                  shill::kDBusObjectProperty,
                                  base::Value(kCellularDeviceObjectPath),
                                  /*notify_changed=*/true);
  device_test_->SetDeviceProperty(kCellularDevicePath,
                                  shill::kDBusObjectProperty, base::Value("/"),
                                  /*notify_changed=*/true);
  device_test_->SetDeviceProperty(kCellularDevicePath,
                                  shill::kDBusObjectProperty,
                                  base::Value(kCellularDeviceObjectPath),
                                  /*notify_changed=*/true);

  base::RunLoop().RunUntilIdle();
}

TEST_F(Network3gppHandlerTest, EmptyDeviceConfig) {
  // This test uses empty carrier lock configuration.
  device_test_->SetDeviceProperty(kCellularDevicePath,
                                  shill::kDBusObjectProperty,
                                  base::Value(kCellularDeviceObjectPath),
                                  /*notify_changed=*/true);
  base::RunLoop().RunUntilIdle();

  // Call SetCarrierLock.
  base::test::TestFuture<CarrierLockResult> set_carrier_lock_future;
  network_3gpp_handler_->SetCarrierLock(std::string(),
                                        set_carrier_lock_future.GetCallback());
  modem_fake_client_->CompleteSetCarrierLock(
      /*result=*/CarrierLockResult::kUnknownError);

  EXPECT_EQ(CarrierLockResult::kUnknownError, set_carrier_lock_future.Get());
}

TEST_F(Network3gppHandlerTest, SetCarrierLock) {
  // This test uses proper object path and sample configuration.
  device_test_->SetDeviceProperty(kCellularDevicePath,
                                  shill::kDBusObjectProperty,
                                  base::Value(kCellularDeviceObjectPath),
                                  /*notify_changed=*/true);
  base::RunLoop().RunUntilIdle();

  // Call SetCarrierLock.
  base::test::TestFuture<CarrierLockResult> set_carrier_lock_future;
  network_3gpp_handler_->SetCarrierLock(
      std::string(kCellularDeviceConfiguration),
      set_carrier_lock_future.GetCallback());
  modem_fake_client_->CompleteSetCarrierLock(
      /*result=*/CarrierLockResult::kSuccess);

  EXPECT_EQ(CarrierLockResult::kSuccess, set_carrier_lock_future.Get());
}

}  // namespace ash