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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qprocess.h>
#include <QtCore/qloggingcategory.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformintegration.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
Q_LOGGING_CATEGORY(lcQml, "qt.qml.tests");
class tst_qml : public QQmlDataTest
{
Q_OBJECT
public:
tst_qml() : QQmlDataTest(QT_QMLTEST_DATADIR) {}
private slots:
void initTestCase() override;
void nonWindow();
void itemAndWindowGeometry_data();
void itemAndWindowGeometry();
private:
QString qmlPath;
};
void tst_qml::initTestCase()
{
QQmlDataTest::initTestCase();
qmlPath = QLibraryInfo::path(QLibraryInfo::BinariesPath);
#if defined(Q_OS_WIN)
qmlPath += QLatin1String("/qml.exe");
#else
qmlPath += QLatin1String("/qml");
#endif
QVERIFY(QFileInfo(qmlPath).exists());
}
void tst_qml::nonWindow()
{
QProcess qml;
qml.start(qmlPath, { testFile("nonWindow.qml") });
QVERIFY(qml.waitForFinished());
QCOMPARE(qml.exitCode(), 0); // Should not exit with code 2
}
void tst_qml::itemAndWindowGeometry_data()
{
QTest::addColumn<QString>("config");
QTest::addColumn<QString>("geometry");
QTest::addColumn<QString>("qmlfile");
QTest::addColumn<QSize>("expectedWindowSize");
QTest::addColumn<QSize>("expectedContentSize");
const QString none; // empty string
auto sizeOrInvalid = [](int w, int h) {
static const bool wm = QGuiApplicationPrivate::platformIntegration()->
hasCapability(QPlatformIntegration::WindowManagement);
return wm ? QSize(w, h) : QSize();
};
QTest::newRow("default: unsized")
<< none << none << "unsizedItem.qml"
<< QSize() << QSize(); // default size depends on window system
QTest::newRow("default: unsized with geometry")
<< none << "100x100+50+50" << "unsizedItem.qml"
<< sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
QTest::newRow("resizeToItem: unsized")
<< "resizeToItem" << none << "unsizedItem.qml"
<< QSize() << QSize(0, 0);
QTest::newRow("resizeToItem: unsized with geometry")
<< "resizeToItem" << "100x100+50+50" << "unsizedItem.qml"
<< sizeOrInvalid(100, 100) << QSize(0, 0);
QTest::newRow("default: sized")
<< none << none << "sizedItem.qml"
<< QSize() << QSize();
QTest::newRow("default: sized with geometry")
<< none << "100x100+50+50" << "sizedItem.qml"
<< sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
QTest::newRow("resizeToItem: sized")
<< "resizeToItem" << none << "sizedItem.qml"
<< sizeOrInvalid(200, 150) << sizeOrInvalid(200, 150);
QTest::newRow("resizeToItem: sized with geometry")
<< "resizeToItem" << "320x240+50+50" << "sizedItem.qml"
<< sizeOrInvalid(320, 240) << QSize(200, 150);
QTest::newRow("default: resizing")
<< none << none << "resizeItem.qml"
<< QSize() << QSize();
QTest::newRow("default: resizing with geometry")
<< none << "100x100+50+50" << "resizeItem.qml"
<< sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
QTest::newRow("resizeToItem: resizing")
<< "resizeToItem" << none << "resizeItem.qml"
<< sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
QTest::newRow("resizeToItem: resizing with geometry")
<< "resizeToItem" << "320x240+50+50" << "resizeItem.qml"
<< sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
}
/*
- A root Item will get put into a Window depending on config (implementations in
tools/qml/ResizeItemToWindow.qml and ResizeWindowToItem.qml).
- The window system will enforce a minimum size.
- In the default configuration, the root Item should then get resized to fit
(QTBUG-114068 / QTBUG-116753).
- In resizeToItem configuration, if the item width/height are not set, the window would
try to be 0x0, but the window system won't allow it.
- This also tests the `--qwindowgeometry` argument: with the default config, the
item should be resized to fit, but not with `-c resizeToItem`.
*/
void tst_qml::itemAndWindowGeometry()
{
#ifdef Q_OS_WIN
QSKIP("console.info does not go to stderr on Windows.");
#endif
QFETCH(QString, config);
QFETCH(QString, geometry);
QFETCH(QString, qmlfile);
QFETCH(QSize, expectedWindowSize);
QFETCH(QSize, expectedContentSize);
QStringList args;
if (!config.isEmpty())
args << "-c" << config;
if (!geometry.isEmpty())
args << "--qwindowgeometry" << geometry;
args << testFile(qmlfile);
QProcess qml;
qml.start(qmlPath, args);
QVERIFY(qml.waitForFinished());
QCOMPARE(qml.exitStatus(), QProcess::NormalExit);
const QByteArray output = qml.readAllStandardError();
const auto sizeLineIndex = output.lastIndexOf("window");
QCOMPARE_GE(sizeLineIndex, 0);
const auto newlineIndex = output.indexOf('\n', sizeLineIndex);
QCOMPARE_GT(newlineIndex, sizeLineIndex);
// expect a line like "window 120 120 content 120 120"
const auto sizes = output.sliced(sizeLineIndex, newlineIndex - sizeLineIndex).split(' ');
QCOMPARE_GE(sizes.size(), 6);
QCOMPARE(sizes[0], "window");
QCOMPARE(sizes[3], "content");
const QSize windowSize(sizes[1].toInt(), sizes[2].toInt());
const QSize contentSize(sizes[4].toInt(), sizes[5].toInt());
qCDebug(lcQml) << sizes
<< "window" << windowSize << "expect" << expectedWindowSize
<< "content" << contentSize << "expect" << expectedContentSize;
QVERIFY(!windowSize.isEmpty());
if (config != "resizeToItem") {
// default config:
// ResizeItemToWindow.qml should have resized the item to its window
QCOMPARE(contentSize, windowSize);
}
// windowSize can be off-by-one on hidpi (e.g. QT_SCALE_FACTOR=2 on xcb);
// perhaps that's a bug somewhere, but so far we aren't testing hidpi on CI
if (expectedWindowSize.isValid())
QCOMPARE(windowSize, expectedWindowSize);
if (expectedContentSize.isValid())
QCOMPARE(contentSize, expectedContentSize);
}
QTEST_MAIN(tst_qml)
#include <tst_qml.moc>
|