1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// 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 "ui/display/manager/display_port_observer.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/manager/test/fake_display_snapshot.h"
namespace display {
namespace {
// Creates fake DP connector sysfs directory as the following.
//
// # ls conn_path
// > connector_id
// > typec_connector
//
// # ls conn_path/typec_connector
// > uevent
bool CreateFakeDpConn(const base::FilePath& conn_path, int id, int port_num) {
if (!base::CreateDirectory(conn_path)) {
return false;
}
auto conn_id = base::StringPrintf("%d", id);
if (!base::WriteFile(conn_path.Append("connector_id"), conn_id)) {
return false;
}
auto typec_conn_path = conn_path.Append("typec_connector");
if (!base::CreateDirectory(typec_conn_path)) {
return false;
}
auto typec_conn_uevent = base::StringPrintf("TYPEC_PORT=port%d", port_num);
if (!base::WriteFile(typec_conn_path.Append("uevent"), typec_conn_uevent)) {
return false;
}
return true;
}
std::unique_ptr<DisplaySnapshot> CreateDisplaySnapshot(
uint64_t base_connector_id,
base::FilePath sys_path) {
return FakeDisplaySnapshot::Builder()
.SetId(1)
.SetNativeMode(gfx::Size(1024, 768))
.SetBaseConnectorId(base_connector_id)
.SetSysPath(sys_path)
.Build();
}
} // namespace
class DisplayPortObserverTest : public testing::Test {
public:
DisplayPortObserverTest() = default;
DisplayPortObserverTest(const DisplayPortObserverTest&) = delete;
DisplayPortObserverTest& operator=(const DisplayPortObserverTest&) = delete;
~DisplayPortObserverTest() override = default;
// testing::Test
void SetUp() override {
display_port_observer_ = std::make_unique<DisplayPortObserver>(
nullptr,
base::BindLambdaForTesting([&](const std::vector<uint32_t>& port_nums) {
cached_port_nums_ = port_nums;
}));
ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
temp_dir_ = scoped_temp_dir_.GetPath();
Test::SetUp();
}
protected:
std::unique_ptr<DisplayPortObserver> display_port_observer_;
base::FilePath temp_dir_;
base::ScopedTempDir scoped_temp_dir_;
base::test::TaskEnvironment task_environment_;
std::vector<uint32_t> cached_port_nums_;
};
TEST_F(DisplayPortObserverTest, OnNoDisplayConnected) {
// 4 Type C ports, each with a dedicated DP connector
ASSERT_TRUE(CreateFakeDpConn(temp_dir_.Append("card0-DP-1"), 256, 0));
ASSERT_TRUE(CreateFakeDpConn(temp_dir_.Append("card0-DP-2"), 266, 1));
ASSERT_TRUE(CreateFakeDpConn(temp_dir_.Append("card0-DP-3"), 275, 2));
ASSERT_TRUE(CreateFakeDpConn(temp_dir_.Append("card0-DP-4"), 284, 3));
// Only internal display with an id not dedicated to any DP connector
std::vector<raw_ptr<DisplaySnapshot, VectorExperimental>> display_states;
auto display_state = CreateDisplaySnapshot(236, temp_dir_);
display_states.push_back(display_state.get());
display_port_observer_->OnDisplayConfigurationChanged(
std::move(display_states));
task_environment_.RunUntilIdle();
EXPECT_TRUE(cached_port_nums_.empty());
}
TEST_F(DisplayPortObserverTest, OnMultipleDisplaysConnected) {
// 4 Type C ports, each with a dedicated DP connector
ASSERT_TRUE(CreateFakeDpConn(temp_dir_.Append("card0-DP-1"), 256, 0));
ASSERT_TRUE(CreateFakeDpConn(temp_dir_.Append("card0-DP-2"), 266, 1));
ASSERT_TRUE(CreateFakeDpConn(temp_dir_.Append("card0-DP-3"), 275, 2));
ASSERT_TRUE(CreateFakeDpConn(temp_dir_.Append("card0-DP-4"), 284, 3));
// 2 displays on port 0 and 1 display on port 2
std::vector<raw_ptr<DisplaySnapshot, VectorExperimental>> display_states;
auto display_state1 = CreateDisplaySnapshot(256, temp_dir_);
display_states.push_back(display_state1.get());
auto display_state2 = CreateDisplaySnapshot(256, temp_dir_);
display_states.push_back(display_state2.get());
auto display_state3 = CreateDisplaySnapshot(275, temp_dir_);
display_states.push_back(display_state3.get());
display_port_observer_->OnDisplayConfigurationChanged(
std::move(display_states));
task_environment_.RunUntilIdle();
const std::vector<uint32_t> kExpectedPortNums{0, 0, 2};
EXPECT_EQ(kExpectedPortNums, cached_port_nums_);
}
} // namespace display
|