fix(log): rotate the log instead of deleting it

This commit is contained in:
Nick Bolton 2026-09-17 12:13:53 +01:00 committed by Chris Rizzitello
parent 217166c06b
commit 23b0d7792d
4 changed files with 123 additions and 1 deletions

View file

@ -138,7 +138,7 @@ bool FileLogOutputter::write(LogLevel::Level, const QString &message)
if (file.size() > s_logFileSizeLimit) {
const auto oldFile = QStringLiteral("%1.1").arg(m_fileName);
QFile::remove(m_fileName);
QFile::remove(oldFile);
QFile::rename(m_fileName, oldFile);
}

View file

@ -29,6 +29,14 @@ create_test(
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(
NAME BaseExceptionTests
DEPENDS base

View 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)

View 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;
};