fix(log): rotate the log instead of deleting it
This commit is contained in:
parent
217166c06b
commit
23b0d7792d
4 changed files with 123 additions and 1 deletions
|
|
@ -138,7 +138,7 @@ bool FileLogOutputter::write(LogLevel::Level, const QString &message)
|
||||||
|
|
||||||
if (file.size() > s_logFileSizeLimit) {
|
if (file.size() > s_logFileSizeLimit) {
|
||||||
const auto oldFile = QStringLiteral("%1.1").arg(m_fileName);
|
const auto oldFile = QStringLiteral("%1.1").arg(m_fileName);
|
||||||
QFile::remove(m_fileName);
|
QFile::remove(oldFile);
|
||||||
QFile::rename(m_fileName, oldFile);
|
QFile::rename(m_fileName, oldFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,14 @@ create_test(
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/base"
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
create_test(
|
||||||
|
NAME FileLogOutputterTests
|
||||||
|
DEPENDS base
|
||||||
|
LIBS arch ${extra_libs}
|
||||||
|
SOURCE FileLogOutputterTests.cpp
|
||||||
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/base"
|
||||||
|
)
|
||||||
|
|
||||||
create_test(
|
create_test(
|
||||||
NAME BaseExceptionTests
|
NAME BaseExceptionTests
|
||||||
DEPENDS base
|
DEPENDS base
|
||||||
|
|
|
||||||
79
src/unittests/base/FileLogOutputterTests.cpp
Normal file
79
src/unittests/base/FileLogOutputterTests.cpp
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Synergy App Ltd
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FileLogOutputterTests.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
void FileLogOutputterTests::init()
|
||||||
|
{
|
||||||
|
QVERIFY(m_dir.isValid());
|
||||||
|
m_fileName = m_dir.filePath(QStringLiteral("deskflow.log"));
|
||||||
|
QFile::remove(m_fileName);
|
||||||
|
QFile::remove(rotatedFileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileLogOutputterTests::rotatedFileName() const
|
||||||
|
{
|
||||||
|
return QStringLiteral("%1.1").arg(m_fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileLogOutputterTests::readAll(const QString &fileName)
|
||||||
|
{
|
||||||
|
QFile file(fileName);
|
||||||
|
if (!file.open(QFile::ReadOnly))
|
||||||
|
return {};
|
||||||
|
return QString::fromUtf8(file.readAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLogOutputterTests::growLogPastSizeLimit(FileLogOutputter &outputter, const QString &marker)
|
||||||
|
{
|
||||||
|
const QString padding(s_paddingSize, QLatin1Char('x'));
|
||||||
|
|
||||||
|
QVERIFY(outputter.write(LogLevel::Level::Info, marker));
|
||||||
|
|
||||||
|
// rotating renames the live log away, so its absence is what ends the loop
|
||||||
|
for (int i = 0; i < s_maxPaddingWrites && QFileInfo::exists(m_fileName); ++i)
|
||||||
|
QVERIFY(outputter.write(LogLevel::Level::Info, padding));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLogOutputterTests::write_multipleMessages_appendsEachLine()
|
||||||
|
{
|
||||||
|
FileLogOutputter outputter(m_fileName);
|
||||||
|
|
||||||
|
QVERIFY(outputter.write(LogLevel::Level::Info, QStringLiteral("first")));
|
||||||
|
QVERIFY(outputter.write(LogLevel::Level::Info, QStringLiteral("second")));
|
||||||
|
|
||||||
|
QCOMPARE(readAll(m_fileName), QStringLiteral("first\nsecond\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLogOutputterTests::write_sizeLimitExceeded_preservesPreviousLog()
|
||||||
|
{
|
||||||
|
FileLogOutputter outputter(m_fileName);
|
||||||
|
|
||||||
|
growLogPastSizeLimit(outputter, QStringLiteral("oldest entry"));
|
||||||
|
|
||||||
|
QVERIFY2(QFileInfo::exists(rotatedFileName()), "log was discarded instead of rotated");
|
||||||
|
QVERIFY(readAll(rotatedFileName()).startsWith(QStringLiteral("oldest entry\n")));
|
||||||
|
|
||||||
|
QVERIFY(outputter.write(LogLevel::Level::Info, QStringLiteral("after rotating")));
|
||||||
|
QCOMPARE(readAll(m_fileName), QStringLiteral("after rotating\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLogOutputterTests::write_rotatedLogExists_replacesIt()
|
||||||
|
{
|
||||||
|
FileLogOutputter outputter(m_fileName);
|
||||||
|
|
||||||
|
growLogPastSizeLimit(outputter, QStringLiteral("first batch"));
|
||||||
|
QVERIFY(readAll(rotatedFileName()).startsWith(QStringLiteral("first batch\n")));
|
||||||
|
|
||||||
|
growLogPastSizeLimit(outputter, QStringLiteral("second batch"));
|
||||||
|
QVERIFY(readAll(rotatedFileName()).startsWith(QStringLiteral("second batch\n")));
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(FileLogOutputterTests)
|
||||||
35
src/unittests/base/FileLogOutputterTests.h
Normal file
35
src/unittests/base/FileLogOutputterTests.h
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Synergy App Ltd
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/LogOutputters.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
|
class FileLogOutputterTests : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void init();
|
||||||
|
void write_multipleMessages_appendsEachLine();
|
||||||
|
void write_sizeLimitExceeded_preservesPreviousLog();
|
||||||
|
void write_rotatedLogExists_replacesIt();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString rotatedFileName() const;
|
||||||
|
void growLogPastSizeLimit(FileLogOutputter &outputter, const QString &marker);
|
||||||
|
static QString readAll(const QString &fileName);
|
||||||
|
|
||||||
|
static constexpr int s_paddingSize = 64 * 1024;
|
||||||
|
static constexpr int s_maxPaddingWrites = 64;
|
||||||
|
|
||||||
|
QTemporaryDir m_dir;
|
||||||
|
QString m_fileName;
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue