Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qabstracttestlogger.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtTest/private/qabstracttestlogger_p.h>
5#include <QtTest/qtestassert.h>
6#include <qbenchmark_p.h>
7#include <qtestresult_p.h>
8
9#include <QtCore/qbytearray.h>
10#include <QtCore/qstring.h>
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <stdarg.h>
15
16#ifndef Q_OS_WIN
17#include <unistd.h>
18#endif
19
20#ifdef Q_OS_ANDROID
21#include <sys/stat.h>
22#endif
23
114{
115 if (!filename) {
116 stream = stdout;
117 return;
118 }
119#if defined(_MSC_VER)
120 if (::fopen_s(&stream, filename, "wt")) {
121#else
122 stream = ::fopen(filename, "wt");
123 if (!stream) {
124#endif
125 fprintf(stderr, "Unable to open file for logging: %s\n", filename);
126 ::exit(1);
127 }
128#ifdef Q_OS_ANDROID
129 else {
130 // Make sure output is world-readable on Android
131 ::chmod(filename, 0666);
132 }
133#endif
134}
135
143{
145 if (stream != stdout)
146 fclose(stream);
147 stream = nullptr;
148}
149
154{
155 return stream == stdout;
156}
157
165{
166 unsigned char *idx = reinterpret_cast<unsigned char *>(str);
167 while (*idx) {
168 if (((*idx < 0x20 && *idx != '\n' && *idx != '\t') || *idx == 0x7f))
169 *idx = '?';
170 ++idx;
171 }
172}
173
182{
184 QTEST_ASSERT(msg);
185
186 char *filtered = new char[strlen(msg) + 1];
187 strcpy(filtered, msg);
188 filterUnprintable(filtered);
189
190 ::fputs(filtered, stream);
191 ::fflush(stream);
192
193 delete [] filtered;
194}
195
208{
209}
210
223{
224}
225
227{
228 for (const auto &m : result)
230}
231
351 const QString &message)
352{
353 QAbstractTestLogger::MessageTypes messageType = [=]() {
354 switch (type) {
360 }
361 Q_UNREACHABLE_RETURN(QAbstractTestLogger::QFatal);
362 }();
363
364 QString formattedMessage = qFormatLogMessage(type, context, message);
365
366 // Note that we explicitly ignore the file and line of the context here,
367 // as that's what QTest::messageHandler used to do when calling the same
368 // overload directly.
369 addMessage(messageType, formattedMessage);
370}
371
372namespace
373{
374 constexpr int MAXSIZE = 1024 * 1024 * 2;
375}
376
377namespace QTest
378{
379
384int qt_asprintf(QTestCharBuffer *str, const char *format, ...)
385{
386 Q_ASSERT(str);
387 int size = str->size();
388 Q_ASSERT(size > 0);
389
390 va_list ap;
391 int res = 0;
392
393 do {
394 va_start(ap, format);
395 res = qvsnprintf(str->data(), size, format, ap);
396 va_end(ap);
397 // vsnprintf() reliably '\0'-terminates
398 Q_ASSERT(res < 0 || str->data()[res < size ? res : size - 1] == '\0');
399 // Note, we're assuming that a result of -1 is always due to running out of space.
400 if (res >= 0 && res < size) // Success
401 break;
402
403 // Buffer wasn't big enough, try again:
404 size *= 2;
405 // If too large or out of memory, take what we have:
406 } while (size <= MAXSIZE && str->reset(size));
407
408 return res;
409}
410
411}
412
413namespace QTestPrivate
414{
415
416void generateTestIdentifier(QTestCharBuffer *identifier, int parts)
417{
418 const char *testObject = parts & TestObject ? QTestResult::currentTestObjectName() : "";
419 const char *testFunction = parts & TestFunction ? (QTestResult::currentTestFunction() ? QTestResult::currentTestFunction() : "UnknownTestFunc") : "";
420 const char *objectFunctionFiller = parts & TestObject && parts & (TestFunction | TestDataTag) ? "::" : "";
421 const char *testFuctionStart = parts & TestFunction ? "(" : "";
422 const char *testFuctionEnd = parts & TestFunction ? ")" : "";
423
424 const char *dataTag = (parts & TestDataTag) && QTestResult::currentDataTag() ? QTestResult::currentDataTag() : "";
425 const char *globalDataTag = (parts & TestDataTag) && QTestResult::currentGlobalDataTag() ? QTestResult::currentGlobalDataTag() : "";
426 const char *tagFiller = (dataTag[0] && globalDataTag[0]) ? ":" : "";
427
428 QTest::qt_asprintf(identifier, "%s%s%s%s%s%s%s%s",
429 testObject, objectFunctionFiller, testFunction, testFuctionStart,
430 globalDataTag, tagFiller, dataTag, testFuctionEnd);
431}
432
433// strcat() for QTestCharBuffer objects:
434bool appendCharBuffer(QTestCharBuffer *accumulator, const QTestCharBuffer &more)
435{
436 const auto bufsize = [](const QTestCharBuffer &buf) -> int {
437 const int max = buf.size();
438 return max > 0 ? int(qstrnlen(buf.constData(), max)) : 0;
439 };
440 const int extra = bufsize(more);
441 if (extra <= 0)
442 return true; // Nothing to do, fatuous success
443
444 const int oldsize = bufsize(*accumulator);
445 const int newsize = oldsize + extra + 1; // 1 for final '\0'
446 if (newsize > MAXSIZE || !accumulator->resize(newsize))
447 return false; // too big or unable to grow
448
449 char *tail = accumulator->data() + oldsize;
450 memcpy(tail, more.constData(), extra);
451 tail[extra] = '\0';
452 return true;
453}
454
455}
456
void outputString(const char *msg)
Convenience method to write msg to the output stream.
virtual ~QAbstractTestLogger()
Destroys the logger object.
virtual void addBenchmarkResult(const QBenchmarkResult &result)=0
This virtual method is called after a benchmark has been run enough times to produce usable data.
bool isLoggingToStdout() const
Returns true if the output stream is standard output.
QAbstractTestLogger(const char *filename)
Constructs the base-class parts of the logger.
virtual void startLogging()
Called before the start of a test run.
virtual void addMessage(QtMsgType, const QMessageLogContext &, const QString &)
This is an overloaded member function, provided for convenience. It differs from the above function o...
MessageTypes
The members whose names begin with Q describe messages that originate in calls, by the test or code u...
void filterUnprintable(char *str) const
Helper utility to blot out unprintable characters in str.
virtual void addBenchmarkResults(const QList< QBenchmarkResult > &result)
virtual void stopLogging()
Called after the end of a test run.
Definition qlist.h:74
\inmodule QtCore
Definition qlogging.h:39
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
static const char * currentTestObjectName()
static const char * currentGlobalDataTag()
static const char * currentDataTag()
static const char * currentTestFunction()
QString str
[2]
Combined button and popup list for selecting options.
void generateTestIdentifier(QTestCharBuffer *identifier, int parts)
bool appendCharBuffer(QTestCharBuffer *accumulator, const QTestCharBuffer &more)
int qt_asprintf(QTestCharBuffer *str, const char *format,...)
static void * context
Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap)
size_t qstrnlen(const char *str, size_t maxlen)
EGLStreamKHR stream
Q_CORE_EXPORT QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, const QString &buf)
QtMsgType
Definition qlogging.h:29
@ QtCriticalMsg
Definition qlogging.h:32
@ QtInfoMsg
Definition qlogging.h:34
@ QtWarningMsg
Definition qlogging.h:31
@ QtFatalMsg
Definition qlogging.h:33
@ QtDebugMsg
Definition qlogging.h:30
const GLfloat * m
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum type
GLenum GLuint GLenum GLsizei const GLchar * buf
GLsizei bufsize
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei GLsizei GLenum format
GLboolean reset
GLuint res
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QTEST_ASSERT(cond)
Definition qtestassert.h:12
void testObject()
[11]
const char * constData() const
bool resize(int newSize)