2
* Copyright (C) 2015-2016 Canonical, Ltd.
4
* This program is free software: you can redistribute it and/or modify it under
5
* the terms of the GNU Lesser General Public License version 3, as published by
6
* the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but WITHOUT
9
* ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10
* SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
#include <gtest/gtest.h>
18
#include "gmock_fixes.h"
20
#include "stub_display.h"
21
#include "mock_main_loop.h"
22
#include "mock_gl_display_buffer.h"
23
#include "qtcompositor.h"
24
#include "fake_displayconfigurationoutput.h"
26
#include <mir/test/doubles/stub_display_buffer.h>
28
#include "testable_screensmodel.h"
30
#include "screenwindow.h"
32
#include <QGuiApplication>
33
#include <QLoggingCategory>
35
using namespace ::testing;
37
namespace mg = mir::graphics;
38
namespace geom = mir::geometry;
40
using StubDisplayBuffer = mir::test::doubles::StubDisplayBuffer;
42
class ScreensModelTest : public ::testing::Test {
44
void SetUp() override;
45
void TearDown() override;
47
ScreensModel *screensModel;
48
std::shared_ptr<StubDisplay> display;
49
std::shared_ptr<StubDisplayListener> displayListener;
50
std::shared_ptr<QtCompositor> compositor;
54
void ScreensModelTest::SetUp()
56
setenv("QT_QPA_PLATFORM", "minimal", 1);
57
Screen::skipDBusRegistration = true;
59
// We don't want the logging spam cluttering the test results
60
QLoggingCategory::setFilterRules(QStringLiteral("qtmir.*=false"));
62
screensModel = new TestableScreensModel;
63
display = std::make_shared<StubDisplay>();
64
displayListener = std::make_shared<StubDisplayListener>();
65
compositor = std::make_shared<QtCompositor>();
67
static_cast<TestableScreensModel*>(screensModel)->do_init(display, compositor, displayListener);
70
char **argv = nullptr;
71
setenv("QT_QPA_PLATFORM", "minimal", 1);
72
app = new QGuiApplication(argc, argv);
75
void ScreensModelTest::TearDown()
81
TEST_F(ScreensModelTest, SingleScreenFound)
83
// Set up display state
84
std::vector<mg::DisplayConfigurationOutput> config{fakeOutput1};
85
std::vector<MockGLDisplayBuffer*> bufferConfig; // only used to match buffer with display, unecessary here
86
display->setFakeConfiguration(config, bufferConfig);
88
screensModel->update();
90
ASSERT_EQ(1, screensModel->screens().count());
91
Screen* screen = screensModel->screens().first();
92
EXPECT_EQ(QRect(0, 0, 150, 200), screen->geometry());
95
TEST_F(ScreensModelTest, MultipleScreenFound)
97
std::vector<mg::DisplayConfigurationOutput> config{fakeOutput1, fakeOutput2};
98
std::vector<MockGLDisplayBuffer*> bufferConfig; // only used to match buffer with display, unecessary here
99
display->setFakeConfiguration(config, bufferConfig);
101
screensModel->update();
103
ASSERT_EQ(2, screensModel->screens().count());
104
EXPECT_EQ(QRect(0, 0, 150, 200), screensModel->screens().at(0)->geometry());
105
EXPECT_EQ(QRect(500, 600, 1500, 2000), screensModel->screens().at(1)->geometry());
108
TEST_F(ScreensModelTest, ScreenAdded)
110
std::vector<mg::DisplayConfigurationOutput> config{fakeOutput1};
111
std::vector<MockGLDisplayBuffer*> bufferConfig; // only used to match buffer with display, unecessary here
112
display->setFakeConfiguration(config, bufferConfig);
114
screensModel->update();
116
config.push_back(fakeOutput2);
117
display->setFakeConfiguration(config, bufferConfig);
119
ASSERT_EQ(1, screensModel->screens().count());
120
EXPECT_EQ(QRect(0, 0, 150, 200), screensModel->screens().at(0)->geometry());
122
screensModel->update();
124
ASSERT_EQ(2, screensModel->screens().count());
125
EXPECT_EQ(QRect(0, 0, 150, 200), screensModel->screens().at(0)->geometry());
126
EXPECT_EQ(QRect(500, 600, 1500, 2000), screensModel->screens().at(1)->geometry());
129
TEST_F(ScreensModelTest, ScreenRemoved)
131
std::vector<mg::DisplayConfigurationOutput> config{fakeOutput2, fakeOutput1};
132
std::vector<MockGLDisplayBuffer*> bufferConfig; // only used to match buffer with display, unecessary here
133
display->setFakeConfiguration(config, bufferConfig);
135
screensModel->update();
138
display->setFakeConfiguration(config, bufferConfig);
140
ASSERT_EQ(2, screensModel->screens().count());
141
EXPECT_EQ(QRect(500, 600, 1500, 2000), screensModel->screens().at(0)->geometry());
142
EXPECT_EQ(QRect(0, 0, 150, 200), screensModel->screens().at(1)->geometry());
144
screensModel->update();
146
ASSERT_EQ(1, screensModel->screens().count());
147
EXPECT_EQ(QRect(500, 600, 1500, 2000), screensModel->screens().at(0)->geometry());
150
TEST_F(ScreensModelTest, MatchBufferWithDisplay)
152
std::vector<mg::DisplayConfigurationOutput> config{fakeOutput1};
153
MockGLDisplayBuffer buffer1;
154
std::vector<MockGLDisplayBuffer*> buffers {&buffer1};
156
geom::Rectangle buffer1Geom{{0, 0}, {150, 200}};
157
EXPECT_CALL(buffer1, view_area())
158
.WillRepeatedly(Return(buffer1Geom));
160
display->setFakeConfiguration(config, buffers);
161
screensModel->update();
163
ASSERT_EQ(1, screensModel->screens().count());
164
EXPECT_CALL(buffer1, make_current());
165
static_cast<StubScreen*>(screensModel->screens().at(0))->makeCurrent();
168
TEST_F(ScreensModelTest, MultipleMatchBuffersWithDisplays)
170
std::vector<mg::DisplayConfigurationOutput> config{fakeOutput1, fakeOutput2};
171
MockGLDisplayBuffer buffer1, buffer2;
172
std::vector<MockGLDisplayBuffer*> buffers {&buffer1, &buffer2};
174
geom::Rectangle buffer1Geom{{500, 600}, {1500, 2000}};
175
geom::Rectangle buffer2Geom{{0, 0}, {150, 200}};
176
EXPECT_CALL(buffer1, view_area())
177
.WillRepeatedly(Return(buffer1Geom));
178
EXPECT_CALL(buffer2, view_area())
179
.WillRepeatedly(Return(buffer2Geom));
181
display->setFakeConfiguration(config, buffers);
182
screensModel->update();
184
ASSERT_EQ(2, screensModel->screens().count());
185
EXPECT_CALL(buffer1, make_current());
186
EXPECT_CALL(buffer2, make_current());
187
static_cast<StubScreen*>(screensModel->screens().at(0))->makeCurrent();
188
static_cast<StubScreen*>(screensModel->screens().at(1))->makeCurrent();