chromium/remoting/host/desktop_display_info_loader_chromeos_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 <vector>

#include "base/test/task_environment.h"
#include "remoting/host/chromeos/scoped_fake_ash_proxy.h"
#include "remoting/host/desktop_display_info_loader.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace remoting {

namespace {
using ::testing::ElementsAre;
using ::testing::UnorderedElementsAre;

constexpr DisplayId kAnyId = 1234567890123456789;

auto Id(DisplayId id) {
  return testing::Field("id", &DisplayGeometry::id, testing::Eq(id));
}

auto Origin(int x, int y) {
  return testing::AllOf(
      testing::Field("x", &DisplayGeometry::x, testing::Eq(x)),
      testing::Field("y", &DisplayGeometry::y, testing::Eq(y)));
}

auto Dimensions(uint32_t width, uint32_t height) {
  return testing::AllOf(
      testing::Field("width", &DisplayGeometry::width, testing::Eq(width)),
      testing::Field("height", &DisplayGeometry::height, testing::Eq(height)));
}

auto Dpi(uint32_t dpi) {
  return testing::Field("dpi", &DisplayGeometry::dpi, testing::Eq(dpi));
}

auto IsDefault(bool is_default) {
  return testing::Field("is_default", &DisplayGeometry::is_default,
                        testing::Eq(is_default));
}

template <typename... Matchers>
auto DisplayWith(Matchers... matchers) {
  return testing::AllOf(std::forward<Matchers>(matchers)...);
}

template <typename... Matchers>
auto IsSingleDisplayWith(Matchers... matchers) {
  return ElementsAre(DisplayWith(std::forward<Matchers>(matchers)...));
}

}  // namespace

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

  test::ScopedFakeAshProxy& ash_proxy() { return ash_proxy_; }

  std::vector<DisplayGeometry> CalculateDisplayInfo() {
    return display_info_loader_->GetCurrentDisplayInfo().displays();
  }

 private:
  base::test::SingleThreadTaskEnvironment environment_;
  test::ScopedFakeAshProxy ash_proxy_;

  std::unique_ptr<DesktopDisplayInfoLoader> display_info_loader_ =
      DesktopDisplayInfoLoader::Create();
};

TEST_F(DesktopDisplayInfoLoaderChromeOsTest, ShouldReturnDisplayId) {
  constexpr int64_t kFirstDisplayId = (0xFFl << 40);
  constexpr int64_t kSecondDisplayId = (0xFFl << 42);

  ash_proxy().AddDisplayWithId(kFirstDisplayId);
  ash_proxy().AddDisplayWithId(kSecondDisplayId);

  EXPECT_THAT(CalculateDisplayInfo(),
              ElementsAre(DisplayWith(Id(kFirstDisplayId)),
                          DisplayWith(Id(kSecondDisplayId))));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest, ShouldReturnDisplayBounds) {
  ash_proxy().AddDisplayFromSpecWithId("10+20-1000x500", kAnyId);

  EXPECT_THAT(CalculateDisplayInfo(),
              IsSingleDisplayWith(Origin(10, 20), Dimensions(1000, 500)));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest, ShouldReturnMultipleDisplays) {
  ash_proxy().AddDisplayFromSpecWithId("10+20-1000x500", 111);
  ash_proxy().AddDisplayFromSpecWithId("110+220-2000x1000", 222);

  EXPECT_THAT(
      CalculateDisplayInfo(),
      ElementsAre(
          DisplayWith(Id(111), Origin(10, 20), Dimensions(1000, 500)),
          DisplayWith(Id(222), Origin(110, 220), Dimensions(2000, 1000))));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest,
       ShouldReturnLogicalResolutionWhenDeviceScaleFactorIsSet) {
  ash_proxy().AddDisplayFromSpecWithId("1000x500*2", kAnyId);

  EXPECT_THAT(CalculateDisplayInfo(),
              IsSingleDisplayWith(Dimensions(500, 250)));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest,
       ShouldSetIsDefaultForPrimaryDisplay) {
  ash_proxy().AddDisplayWithId(111);
  ash_proxy().AddPrimaryDisplay(222);

  EXPECT_THAT(CalculateDisplayInfo(),
              UnorderedElementsAre(DisplayWith(Id(222), IsDefault(true)),
                                   DisplayWith(Id(111), IsDefault(false))));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest,
       OriginShouldRespectDeviceScaleFactor) {
  ash_proxy().AddDisplayFromSpecWithId("10+20-1000x500*2", kAnyId);

  EXPECT_THAT(CalculateDisplayInfo(), IsSingleDisplayWith(Origin(5, 10)));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest, ShouldSetDefaultDpi) {
  constexpr int kDefaultDpi = 96;
  ash_proxy().AddDisplayFromSpecWithId("1000x500", kAnyId);

  EXPECT_THAT(CalculateDisplayInfo(), IsSingleDisplayWith(Dpi(kDefaultDpi)));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest, ShouldSetDpiBasedOnScaleFactor) {
  // scale factor = dpi / default_dpi (which is 96)
  const int scale_factor = 3;
  const int expected_dpi = scale_factor * 96;
  ash_proxy().AddDisplayFromSpecWithId("1000x500*3", kAnyId);

  EXPECT_THAT(CalculateDisplayInfo(), IsSingleDisplayWith(Dpi(expected_dpi)));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest,
       ShouldRotateBoundsWhenRotated90Degrees) {
  ash_proxy().AddDisplayFromSpecWithId("1000x500/r", kAnyId);

  EXPECT_THAT(CalculateDisplayInfo(),
              IsSingleDisplayWith(Dimensions(500, 1000)));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest,
       ShouldKeepBoundsWhenRotated180Degrees) {
  ash_proxy().AddDisplayFromSpecWithId("1000x500/u", kAnyId);

  EXPECT_THAT(CalculateDisplayInfo(),
              IsSingleDisplayWith(Dimensions(1000, 500)));
}

TEST_F(DesktopDisplayInfoLoaderChromeOsTest,
       ShouldRotateBoundsWhenRotated270Degrees) {
  ash_proxy().AddDisplayFromSpecWithId("1000x500/l", kAnyId);

  EXPECT_THAT(CalculateDisplayInfo(),
              IsSingleDisplayWith(Dimensions(500, 1000)));
}

}  // namespace remoting