1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30#include <QtGlobal>
31#include <QtAlgorithms>
32#include <QtPrintSupport/qprinterinfo.h>
33
34#include <algorithm>
35
36#ifdef Q_OS_UNIX
37# include <unistd.h>
38# include <sys/types.h>
39# include <sys/wait.h>
40#endif
41
42
43class tst_QPrinterInfo : public QObject
44{
45 Q_OBJECT
46
47public slots:
48#ifdef QT_NO_PRINTER
49 void initTestCase();
50 void cleanupTestCase();
51#else
52private slots:
53#ifndef Q_OS_WIN32
54 void testForDefaultPrinter();
55 void testForPrinters();
56#endif
57 void testForPaperSizes();
58 void testConstructors();
59 void testAssignment();
60 void namedPrinter();
61
62private:
63 QString getDefaultPrinterFromSystem();
64 QStringList getPrintersFromSystem();
65
66#ifdef Q_OS_UNIX
67 QString getOutputFromCommand(const QStringList& command);
68#endif // Q_OS_UNIX
69#endif
70};
71
72
73#ifdef QT_NO_PRINTER
74void tst_QPrinterInfo::initTestCase()
75{
76 QSKIP("This test requires printing support");
77}
78
79void tst_QPrinterInfo::cleanupTestCase()
80{
81 QSKIP("This test requires printing support");
82}
83
84#else
85QString tst_QPrinterInfo::getDefaultPrinterFromSystem()
86{
87 QString printer;
88
89#ifdef Q_OS_WIN32
90 // TODO "cscript c:\windows\system32\prnmngr.vbs -g"
91#endif // Q_OS_WIN32
92#ifdef Q_OS_UNIX
93 QStringList command;
94 command << "lpstat" << "-d";
95 QString output = getOutputFromCommand(command);
96
97 QRegularExpression noDefaultReg("[^:]*no .*default");
98 QRegularExpressionMatch match;
99 match = noDefaultReg.match(subject: output);
100 if (match.hasMatch())
101 return QString();
102
103 QRegularExpression defaultReg("default.*: *([a-zA-Z0-9_-]+)");
104 match = defaultReg.match(subject: output);
105 printer = match.captured(nth: 1);
106#endif // Q_OS_UNIX
107 return printer;
108}
109
110QStringList tst_QPrinterInfo::getPrintersFromSystem()
111{
112 QStringList ans;
113
114#ifdef Q_OS_WIN32
115 // TODO "cscript c:\windows\system32\prnmngr.vbs -l"
116#endif // Q_OS_WIN32
117#ifdef Q_OS_UNIX
118 QStringList command;
119 command << "lpstat" << "-p";
120 QString output = getOutputFromCommand(command);
121 QStringList list = output.split(sep: QChar::fromLatin1(c: '\n'));
122
123 QRegularExpression reg("^[Pp]rinter ([.a-zA-Z0-9-_@]+)");
124 QRegularExpressionMatch match;
125 for (int c = 0; c < list.size(); ++c) {
126 match = reg.match(subject: list[c]);
127 if (match.hasMatch()) {
128 QString printer = match.captured(nth: 1);
129 ans << printer;
130 }
131 }
132#endif // Q_OS_UNIX
133
134 return ans;
135}
136
137#ifdef Q_OS_UNIX
138// This function does roughly the same as the `command substitution` in
139// the shell.
140QString getOutputFromCommandInternal(const QStringList &command)
141{
142// The command execution does nothing on non-unix systems.
143 int pid;
144 int status = 0;
145 int pipePtr[2];
146
147 // Create a pipe that is shared between parent and child process.
148 if (pipe(pipedes: pipePtr) < 0) {
149 return QString();
150 }
151 pid = fork();
152 if (pid < 0) {
153 close(fd: pipePtr[0]);
154 close(fd: pipePtr[1]);
155 return QString();
156 } else if (pid == 0) {
157 // In child.
158 // Close the reading end.
159 close(fd: pipePtr[0]);
160 // Redirect stdout to the pipe.
161 if (dup2(fd: pipePtr[1], fd2: 1) < 0) {
162 exit(status: 1);
163 }
164
165 char** argv = new char*[command.size()+1];
166 for (int c = 0; c < command.size(); ++c) {
167 argv[c] = new char[command[c].size()+1];
168 strcpy(dest: argv[c], src: command[c].toLatin1().data());
169 }
170 argv[command.size()] = NULL;
171 execvp(file: argv[0], argv: argv);
172 // Shouldn't get here, but it's possible if command is not found.
173 close(fd: pipePtr[1]);
174 close(fd: 1);
175 for (int c = 0; c < command.size(); ++c) {
176 delete [] argv[c];
177 }
178 delete [] argv;
179 exit(status: 1);
180 } else {
181 // In parent.
182 // Close the writing end.
183 close(fd: pipePtr[1]);
184
185 QFile pipeRead;
186 if (!pipeRead.open(fd: pipePtr[0], ioFlags: QIODevice::ReadOnly)) {
187 close(fd: pipePtr[0]);
188 return QString();
189 }
190 QByteArray array;
191 array = pipeRead.readAll();
192 pipeRead.close();
193 close(fd: pipePtr[0]);
194 wait(stat_loc: &status);
195 return QString(array);
196 }
197}
198
199QString tst_QPrinterInfo::getOutputFromCommand(const QStringList &command)
200{
201 // Forces the ouptut from the command to be in English
202 const QByteArray origSoftwareEnv = qgetenv(varName: "SOFTWARE");
203 qputenv(varName: "SOFTWARE", value: QByteArray());
204 QString output = getOutputFromCommandInternal(command);
205 qputenv(varName: "SOFTWARE", value: origSoftwareEnv);
206 return output;
207}
208#endif
209
210// Windows test support not yet implemented
211#ifndef Q_OS_WIN32
212void tst_QPrinterInfo::testForDefaultPrinter()
213{
214 QString testPrinter = getDefaultPrinterFromSystem();
215 QString defaultPrinter = QPrinterInfo::defaultPrinter().printerName();
216 QString availablePrinter;
217 int availablePrinterDefaults = 0;
218
219 QList<QPrinterInfo> list = QPrinterInfo::availablePrinters();
220 for (int c = 0; c < list.size(); ++c) {
221 if (list[c].isDefault()) {
222 availablePrinter = list.at(i: c).printerName();
223 ++availablePrinterDefaults;
224 }
225 }
226
227 qDebug() << "Test believes Default Printer = " << testPrinter;
228 qDebug() << "QPrinterInfo::defaultPrinter() believes Default Printer = " << defaultPrinter;
229 qDebug() << "QPrinterInfo::availablePrinters() believes Default Printer = " << availablePrinter;
230
231 QCOMPARE(testPrinter, defaultPrinter);
232 QCOMPARE(testPrinter, availablePrinter);
233 if (!availablePrinter.isEmpty())
234 QCOMPARE(availablePrinterDefaults, 1);
235}
236#endif
237
238// Windows test support not yet implemented
239#ifndef Q_OS_WIN32
240void tst_QPrinterInfo::testForPrinters()
241{
242 QStringList testPrinters = getPrintersFromSystem();
243
244 QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters();
245 QStringList qtPrinters;
246 for (int i = 0; i < printers.size(); ++i)
247 qtPrinters.append(t: printers.at(i).printerName());
248
249 std::sort(first: testPrinters.begin(), last: testPrinters.end());
250 std::sort(first: qtPrinters.begin(), last: qtPrinters.end());
251
252 qDebug() << "Test believes Available Printers = " << testPrinters;
253 qDebug() << "QPrinterInfo::availablePrinters() believes Available Printers = " << qtPrinters;
254
255 QCOMPARE(qtPrinters.size(), testPrinters.size());
256
257 for (int i = 0; i < testPrinters.size(); ++i)
258 QCOMPARE(qtPrinters.at(i), testPrinters.at(i));
259}
260#endif
261
262void tst_QPrinterInfo::testForPaperSizes()
263{
264 // TODO Old PaperSize test dependent on physical printer installed, new generic test required
265 // In the meantime just exercise the code path and print-out for inspection.
266
267 QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters();
268 for (int i = 0; i < printers.size(); ++i) {
269 qDebug() << "Printer : " << printers.at(i).printerName() << printers.at(i).defaultPageSize();
270 qDebug() << "Paper Sizes : " << printers.at(i).supportedPageSizes();
271 qDebug() << "Custom Sizes : " << printers.at(i).supportsCustomPageSizes();
272 qDebug() << "Physical Sizes: " << printers.at(i).minimumPhysicalPageSize()
273 << printers.at(i).maximumPhysicalPageSize();
274 qDebug() << "";
275 }
276}
277
278void tst_QPrinterInfo::testConstructors()
279{
280 QPrinterInfo null;
281 QCOMPARE(null.printerName(), QString());
282 QVERIFY(null.isNull());
283
284 QPrinterInfo null2(null);
285 QVERIFY(null2.isNull());
286
287 QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters();
288
289 for (int i = 0; i < printers.size(); ++i) {
290 QPrinterInfo copy1(printers.at(i));
291 QCOMPARE(copy1.printerName(), printers.at(i).printerName());
292 QCOMPARE(copy1.description(), printers.at(i).description());
293 QCOMPARE(copy1.location(), printers.at(i).location());
294 QCOMPARE(copy1.makeAndModel(), printers.at(i).makeAndModel());
295 QCOMPARE(copy1.isNull(), printers.at(i).isNull());
296 QCOMPARE(copy1.isDefault(), printers.at(i).isDefault());
297 QCOMPARE(copy1.isRemote(), printers.at(i).isRemote());
298 QCOMPARE(copy1.state(), printers.at(i).state());
299 QCOMPARE(copy1.supportedPageSizes(), printers.at(i).supportedPageSizes());
300 QCOMPARE(copy1.defaultPageSize(), printers.at(i).defaultPageSize());
301 QCOMPARE(copy1.supportsCustomPageSizes(), printers.at(i).supportsCustomPageSizes());
302 QCOMPARE(copy1.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize());
303 QCOMPARE(copy1.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize());
304 QCOMPARE(copy1.supportedPageSizes(), printers.at(i).supportedPageSizes());
305#if QT_DEPRECATED_SINCE(5, 3)
306QT_WARNING_PUSH
307QT_WARNING_DISABLE_DEPRECATED
308 QCOMPARE(copy1.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames());
309QT_WARNING_POP
310#endif
311 QCOMPARE(copy1.supportedResolutions(), printers.at(i).supportedResolutions());
312 QCOMPARE(copy1.defaultDuplexMode(), printers.at(i).defaultDuplexMode());
313 QCOMPARE(copy1.supportedDuplexModes(), printers.at(i).supportedDuplexModes());
314
315 QPrinter printer(printers.at(i));
316 QPrinterInfo copy2(printer);
317 QCOMPARE(copy2.printerName(), printers.at(i).printerName());
318 QCOMPARE(copy2.description(), printers.at(i).description());
319 QCOMPARE(copy2.location(), printers.at(i).location());
320 QCOMPARE(copy2.makeAndModel(), printers.at(i).makeAndModel());
321 QCOMPARE(copy2.isNull(), printers.at(i).isNull());
322 QCOMPARE(copy2.isDefault(), printers.at(i).isDefault());
323 QCOMPARE(copy2.isRemote(), printers.at(i).isRemote());
324 QCOMPARE(copy2.state(), printers.at(i).state());
325 QCOMPARE(copy2.supportedPageSizes(), printers.at(i).supportedPageSizes());
326 QCOMPARE(copy2.defaultPageSize(), printers.at(i).defaultPageSize());
327 QCOMPARE(copy2.supportsCustomPageSizes(), printers.at(i).supportsCustomPageSizes());
328 QCOMPARE(copy2.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize());
329 QCOMPARE(copy2.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize());
330 QCOMPARE(copy2.supportedPageSizes(), printers.at(i).supportedPageSizes());
331#if QT_DEPRECATED_SINCE(5, 3)
332 QT_WARNING_PUSH
333 QT_WARNING_DISABLE_DEPRECATED
334 QCOMPARE(copy2.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames());
335 QT_WARNING_POP
336#endif
337 QCOMPARE(copy2.supportedResolutions(), printers.at(i).supportedResolutions());
338 QCOMPARE(copy2.defaultDuplexMode(), printers.at(i).defaultDuplexMode());
339 QCOMPARE(copy2.supportedDuplexModes(), printers.at(i).supportedDuplexModes());
340 }
341}
342
343void tst_QPrinterInfo::testAssignment()
344{
345 QPrinterInfo null;
346 QVERIFY(null.isNull());
347 QPrinterInfo null2;
348 null2 = null;
349 QVERIFY(null2.isNull());
350
351 QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters();
352
353 for (int i = 0; i < printers.size(); ++i) {
354 QPrinterInfo copy;
355 copy = printers.at(i);
356 QCOMPARE(copy.printerName(), printers.at(i).printerName());
357 QCOMPARE(copy.description(), printers.at(i).description());
358 QCOMPARE(copy.location(), printers.at(i).location());
359 QCOMPARE(copy.makeAndModel(), printers.at(i).makeAndModel());
360 QCOMPARE(copy.isNull(), printers.at(i).isNull());
361 QCOMPARE(copy.isDefault(), printers.at(i).isDefault());
362 QCOMPARE(copy.isRemote(), printers.at(i).isRemote());
363 QCOMPARE(copy.state(), printers.at(i).state());
364 QCOMPARE(copy.supportedPageSizes(), printers.at(i).supportedPageSizes());
365 QCOMPARE(copy.defaultPageSize(), printers.at(i).defaultPageSize());
366 QCOMPARE(copy.supportsCustomPageSizes(), printers.at(i).supportsCustomPageSizes());
367 QCOMPARE(copy.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize());
368 QCOMPARE(copy.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize());
369 QCOMPARE(copy.supportedResolutions(), printers.at(i).supportedResolutions());
370 QCOMPARE(copy.defaultDuplexMode(), printers.at(i).defaultDuplexMode());
371 QCOMPARE(copy.supportedDuplexModes(), printers.at(i).supportedDuplexModes());
372 }
373}
374
375void tst_QPrinterInfo::namedPrinter()
376{
377 QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters();
378
379 QStringList printerNames;
380
381 foreach (const QPrinterInfo &pi, printers) {
382 QPrinterInfo pi2 = QPrinterInfo::printerInfo(printerName: pi.printerName());
383 QCOMPARE(pi2.printerName(), pi.printerName());
384 QCOMPARE(pi2.description(), pi.description());
385 QCOMPARE(pi2.location(), pi.location());
386 QCOMPARE(pi2.makeAndModel(), pi.makeAndModel());
387 QCOMPARE(pi2.isNull(), pi.isNull());
388 QCOMPARE(pi2.isDefault(), pi.isDefault());
389 QCOMPARE(pi2.isRemote(), pi.isRemote());
390 QCOMPARE(pi2.supportedPageSizes(), pi.supportedPageSizes());
391 QCOMPARE(pi2.defaultPageSize(), pi.defaultPageSize());
392 QCOMPARE(pi2.supportsCustomPageSizes(), pi.supportsCustomPageSizes());
393 QCOMPARE(pi2.minimumPhysicalPageSize(), pi.minimumPhysicalPageSize());
394 QCOMPARE(pi2.maximumPhysicalPageSize(), pi.maximumPhysicalPageSize());
395 QCOMPARE(pi2.supportedResolutions(), pi.supportedResolutions());
396 QCOMPARE(pi2.defaultDuplexMode(), pi.defaultDuplexMode());
397 QCOMPARE(pi2.supportedDuplexModes(), pi.supportedDuplexModes());
398 }
399}
400#endif // QT_NO_PRINTER
401
402QTEST_MAIN(tst_QPrinterInfo)
403#include "tst_qprinterinfo.moc"
404

source code of qtbase/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp