File: wayland_display_output_unittest.cc

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (136 lines) | stat: -rw-r--r-- 5,375 bytes parent folder | download | duplicates (7)
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
// 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 "components/exo/wayland/wayland_display_output.h"

#include <cstdint>

#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "components/exo/wayland/output_controller_test_api.h"
#include "components/exo/wayland/test/client_util.h"
#include "components/exo/wayland/test/server_util.h"
#include "components/exo/wayland/test/wayland_server_test.h"
#include "components/exo/wayland/wayland_display_observer.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace exo::wayland {

using WaylandDisplayOutputTest = test::WaylandServerTest;

TEST_F(WaylandDisplayOutputTest, DelayedSelfDestruct) {
  class ClientData : public test::TestClient::CustomData {
   public:
    raw_ptr<wl_output, DanglingUntriaged> output = nullptr;
  };

  // Start with 2 displays.
  UpdateDisplay("800x600,1024x786");

  // Store info about the 2nd display on the client.
  test::ResourceKey output_resource_key;
  PostToClientAndWait([&](test::TestClient* client) {
    auto data = std::make_unique<ClientData>();
    // This gets the latest bound output on the client side, which should be the
    // 2nd display here.
    ASSERT_EQ(client->globals().outputs.size(), 2u);
    data->output = client->globals().outputs.back().get();
    output_resource_key = test::client_util::GetResourceKey(data->output);
    client->set_data(std::move(data));
  });

  auto* display_handler =
      test::server_util::GetUserDataForResource<WaylandDisplayHandler>(
          server_.get(), output_resource_key);
  EXPECT_EQ(display_handler->id(), GetSecondaryDisplay().id());

  // Remove the 2nd display.
  UpdateDisplay("800x600");

  // Fast forward until at least one delete has been attempted.
  task_environment()->FastForwardBy(WaylandDisplayOutput::kDeleteTaskDelay *
                                    1.5);

  // Try releasing now and check for client error.
  PostToClientAndWait([&](test::TestClient* client) {
    auto* data = client->GetDataAs<ClientData>();
    ASSERT_EQ(client->globals().outputs.size(), 2u);
    EXPECT_EQ(data->output, client->globals().outputs.back().get());
    wl_output_release(client->globals().outputs.back().release());
    client->Roundtrip();
    EXPECT_EQ(wl_display_get_error(client->display()), 0);
  });
}

// Verify that in the case where an output is added and removed quickly before
// the client's initial bind, the server still waits for the full amount of
// delete delays before deleting the global resource.
TEST_F(WaylandDisplayOutputTest, DelayedSelfDestructBeforeFirstBind) {
  UpdateDisplay("800x600");

  // Block client thread so the initial bind request doesn't happen yet.
  base::WaitableEvent block_bind_event;
  ASSERT_TRUE(client_thread_->task_runner()->PostTask(
      FROM_HERE, base::BindLambdaForTesting([&] { block_bind_event.Wait(); })));

  // Quickly add then remove a 2nd display while the client is blocked.
  UpdateDisplay("800x600,1024x786");
  UpdateDisplay("800x600");

  // Fast forward until at least one delete has been attempted.
  task_environment()->FastForwardBy(WaylandDisplayOutput::kDeleteTaskDelay *
                                    1.5);

  // Unblock client thread so the bind request happens now.
  block_bind_event.Signal();
  client_thread_->FlushForTesting();

  // Check for client error.
  PostToClientAndWait([&](test::TestClient* client) {
    client->Roundtrip();
    EXPECT_EQ(wl_display_get_error(client->display()), 0);
  });

  // Clean up client's 2nd output object that was removed.
  PostToClientAndWait([&](test::TestClient* client) {
    wl_output_release(client->globals().outputs.back().release());
  });
}

// Tests to ensure exo processes added displays before removed displays for
// display configuration updates. This ensures exo's clients always see a valid
// Output during such configuration updates.
TEST_F(WaylandDisplayOutputTest, MaintainsNonEmptyOutputList) {
  // Start with 2 displays.
  UpdateDisplay("300x400,500x600");

  // Update to a new display configuration. The total global Outputs maintained
  // by exo should remain non-zero while processing the change (exo will CHECK
  // crash if it enters a zero output state).
  UpdateDisplay("700x800,900x1000", /*from_native_platform=*/false,
                /*generate_new_ids=*/true);
}

// Ensures metrics are correctly initialized and updated.
TEST_F(WaylandDisplayOutputTest, InitializesAndUpdatesMetrics) {
  // Start with a typical display configuration and confirm dimensions are
  // reflected in the metrics.
  UpdateDisplay("800x600");
  const int64_t display_id =
      display::Screen::GetScreen()->GetAllDisplays()[0].id();
  OutputControllerTestApi output_controller_test_api(
      *server_->output_controller_for_testing());
  WaylandDisplayOutput* display_output =
      output_controller_test_api.GetWaylandDisplayOutput(display_id);
  EXPECT_EQ(gfx::Size(800, 600), display_output->metrics().logical_size);

  // Update display dimensions, this should be reflected in the metrics.
  UpdateDisplay("1200x800");
  EXPECT_EQ(gfx::Size(1200, 800), display_output->metrics().logical_size);
}

}  // namespace exo::wayland