chromium/chrome/browser/ash/crosapi/cec_private_ash_unittest.cc

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

#include "chrome/browser/ash/crosapi/cec_private_ash.h"

#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "chromeos/ash/components/dbus/cec_service/cec_service_client.h"
#include "chromeos/ash/components/dbus/cec_service/fake_cec_service_client.h"
#include "chromeos/crosapi/mojom/cec_private.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace crosapi {

using ::base::test::TestFuture;
using DisplayPowerStates = const std::vector<mojom::PowerState>&;

class CecPrivateAshTest : public ::testing::Test {
 public:
  void SetUp() override {
    if (ash::CecServiceClient::Get() == nullptr) {
      ash::CecServiceClient::InitializeFake();
    }
    cec_fake_ =
        static_cast<ash::FakeCecServiceClient*>(ash::CecServiceClient::Get());
    CecPrivateAshTest::cec_fake_->reset();
  }

 protected:
  static raw_ptr<ash::FakeCecServiceClient> cec_fake_;
  CecPrivateAsh cec_private_ash_;
};

raw_ptr<ash::FakeCecServiceClient> CecPrivateAshTest::cec_fake_ = nullptr;

TEST_F(CecPrivateAshTest, SendStandBy) {
  ASSERT_EQ(0, CecPrivateAshTest::cec_fake_->stand_by_call_count());

  TestFuture<void> cb;
  cec_private_ash_.SendStandBy(cb.GetCallback());
  EXPECT_TRUE(cb.Wait());

  ASSERT_EQ(1, CecPrivateAshTest::cec_fake_->stand_by_call_count());
}

TEST_F(CecPrivateAshTest, SendWakeUp) {
  ASSERT_EQ(0, CecPrivateAshTest::cec_fake_->wake_up_call_count());

  TestFuture<void> cb;
  cec_private_ash_.SendWakeUp(cb.GetCallback());
  EXPECT_TRUE(cb.Wait());

  ASSERT_EQ(1, CecPrivateAshTest::cec_fake_->wake_up_call_count());
}

TEST_F(CecPrivateAshTest, QueryPowerStateSeveralDevices) {
  // The fake dbus cec client demands that the query runs in a
  // SingleThreadTaskRunner
  base::test::SingleThreadTaskEnvironment task_environment;

  CecPrivateAshTest::cec_fake_->set_tv_power_states(
      {ash::CecServiceClient::PowerState::kOn,
       ash::CecServiceClient::PowerState::kStandBy,
       ash::CecServiceClient::PowerState::kTransitioningToStandBy});

  TestFuture<DisplayPowerStates> cb;
  cec_private_ash_.QueryDisplayCecPowerState(cb.GetCallback());
  EXPECT_EQ(cb.Get(), std::vector<mojom::PowerState>(
                          {mojom::PowerState::kOn, mojom::PowerState::kStandBy,
                           mojom::PowerState::kTransitioningToStandBy}));
}

TEST_F(CecPrivateAshTest, QueryPowerStateNoDevices) {
  // The fake dbus cec client demands that the query runs in a
  // SingleThreadTaskRunner
  base::test::SingleThreadTaskEnvironment task_environment;

  TestFuture<DisplayPowerStates> cb;
  cec_private_ash_.QueryDisplayCecPowerState(cb.GetCallback());
  EXPECT_EQ(0u, cb.Get().size());
}

TEST_F(CecPrivateAshTest, StandByPropagates) {
  // The fake dbus cec client demands that the query runs in a
  // SingleThreadTaskRunner
  base::test::SingleThreadTaskEnvironment task_environment;

  CecPrivateAshTest::cec_fake_->set_tv_power_states(
      {ash::CecServiceClient::PowerState::kOn,
       ash::CecServiceClient::PowerState::kStandBy,
       ash::CecServiceClient::PowerState::kTransitioningToStandBy});
  TestFuture<void> standby_cb;
  cec_private_ash_.SendStandBy(standby_cb.GetCallback());
  ASSERT_TRUE(standby_cb.Wait());

  TestFuture<DisplayPowerStates> query_cb;
  cec_private_ash_.QueryDisplayCecPowerState(query_cb.GetCallback());
  EXPECT_EQ(query_cb.Get(),
            std::vector<mojom::PowerState>({mojom::PowerState::kStandBy,
                                            mojom::PowerState::kStandBy,
                                            mojom::PowerState::kStandBy}));
}

TEST_F(CecPrivateAshTest, WakePropagates) {
  // The fake dbus cec client demands that the query runs in a
  // SingleThreadTaskRunner
  base::test::SingleThreadTaskEnvironment task_environment;

  CecPrivateAshTest::cec_fake_->set_tv_power_states(
      {ash::CecServiceClient::PowerState::kOn,
       ash::CecServiceClient::PowerState::kStandBy,
       ash::CecServiceClient::PowerState::kTransitioningToStandBy});
  TestFuture<void> wake_cb;
  cec_private_ash_.SendWakeUp(wake_cb.GetCallback());
  ASSERT_TRUE(wake_cb.Wait());

  TestFuture<DisplayPowerStates> query_cb;
  cec_private_ash_.QueryDisplayCecPowerState(query_cb.GetCallback());
  EXPECT_EQ(query_cb.Get(), std::vector<mojom::PowerState>(
                                {mojom::PowerState::kOn, mojom::PowerState::kOn,
                                 mojom::PowerState::kOn}));
}

TEST_F(CecPrivateAshTest, HandleUninitializedDbusClient) {
  cec_fake_ = nullptr;
  ash::CecServiceClient::Shutdown();
  ASSERT_EQ(ash::CecServiceClient::Get(), nullptr);

  // All these cec_private_ash_ calls are now working with a null dbus client.
  TestFuture<void> standby_cb;
  cec_private_ash_.SendStandBy(standby_cb.GetCallback());
  TestFuture<void> wakeup_cb;
  cec_private_ash_.SendWakeUp(wakeup_cb.GetCallback());
  TestFuture<DisplayPowerStates> query_cb;
  cec_private_ash_.QueryDisplayCecPowerState(query_cb.GetCallback());
  EXPECT_EQ(query_cb.Get(), std::vector<mojom::PowerState>());
}

}  // namespace crosapi