Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
# SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: LGPL-3.0-or-later
cmake_minimum_required(VERSION 3.16)
Expand All @@ -7,11 +7,14 @@ set (VERSION "1.0.0" CACHE STRING "define project version")

project(dde-services)

include(CTest)

if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX /usr)
endif()

include(GNUInstallDirs)
include(CTest)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
# 设置二进制输出目录 方便调试
Expand All @@ -23,4 +26,6 @@ set(DTK_VERSION_MAJOR 6)

add_subdirectory("src")


if(BUILD_TESTING)
add_subdirectory("tests")
endif()
143 changes: 143 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: LGPL-3.0-or-later

# Top-level test directory for dde-services.
#
# Framework: Qt6::Test, consistent with the existing
# src/plugin-qt/shortcut/tests suite (Qt6::Test + add_test, gated by
# BUILD_TESTING). The project root enables BUILD_TESTING via include(CTest).
#
# This directory lives at the project root (not inside any plugin) on purpose:
# the thememanager / wallpaperslideshow / xsettings plugins build their sources
# with `file(GLOB_RECURSE)`, so a per-plugin tests/ tree would be pulled into
# the plugin MODULE and fail to link. Each test executable here compiles *only*
# the production source under test plus the test file, mirroring the shortcut
# tests' registration style, so no plugin MODULE is required to run the tests.

set(CMAKE_AUTOMOC ON)

find_package(Qt6 REQUIRED COMPONENTS Core DBus Gui Test)

set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)

# ---------------------------------------------------------------------------
# thememanager: SunriseSunset pure-math unit test
# ---------------------------------------------------------------------------
add_executable(tst-sunrisesunset
tst_sunrisesunset.cpp
${SRC_DIR}/plugin-qt/thememanager/sunrisesunset.cpp
)
target_include_directories(tst-sunrisesunset PRIVATE
${SRC_DIR}/plugin-qt/thememanager
)
target_link_libraries(tst-sunrisesunset PRIVATE Qt6::Core Qt6::Test)
add_test(NAME thememanager-sunrisesunset COMMAND tst-sunrisesunset)

# ---------------------------------------------------------------------------
# wallpaperslideshow: utils helper unit test
# ---------------------------------------------------------------------------
add_executable(tst-wpssl-utils
tst_wpssl_utils.cpp
${SRC_DIR}/plugin-qt/wallpaperslideshow/utils.cpp
)
target_include_directories(tst-wpssl-utils PRIVATE
${SRC_DIR}/plugin-qt/wallpaperslideshow
)
target_link_libraries(tst-wpssl-utils PRIVATE Qt6::Core Qt6::DBus Qt6::Test)
add_test(NAME wallpaperslideshow-utils COMMAND tst-wpssl-utils)
# writeWallpaperConfig writes to a path derived from XDG_CONFIG_HOME at
# static-init time; redirect it to a throwaway build-dir path so the test
# does not pollute the real user config dir. (The test slot itself QSKIPs
# when XDG_CONFIG_HOME is unset, e.g. when the binary is run directly.)
set_tests_properties(wallpaperslideshow-utils PROPERTIES
ENVIRONMENT "XDG_CONFIG_HOME=${CMAKE_BINARY_DIR}/dde_svc_test_xdgconfig")

# ---------------------------------------------------------------------------
# wallpaperslideshow: FormatPicture MIME mapping unit test
# ---------------------------------------------------------------------------
add_executable(tst-format
tst_format.cpp
${SRC_DIR}/plugin-qt/wallpaperslideshow/background/format.cpp
)
target_include_directories(tst-format PRIVATE
${SRC_DIR}/plugin-qt/wallpaperslideshow/background
)
target_link_libraries(tst-format PRIVATE Qt6::Core Qt6::Gui Qt6::Test)
add_test(NAME wallpaperslideshow-format COMMAND tst-format)

# ---------------------------------------------------------------------------
# wallpaperslideshow: org.deepin.dde.WallpaperSlideshow D-Bus contract test
# ---------------------------------------------------------------------------
# Generate the production adaptor from the project introspection XML, wrapping
# the test-side FakeWallpaperSlideshowService, so the interface contract is
# validated against a real D-Bus connection.
qt_add_dbus_adaptor(WSS_ADAPTOR_SOURCES
${SRC_DIR}/plugin-qt/wallpaperslideshow/org.deepin.dde.WallpaperSlideshow.xml
${CMAKE_CURRENT_SOURCE_DIR}/fakeservice.h
FakeWallpaperSlideshowService
wallpaperslideshowadaptor
WallpaperSlideshowAdaptor
)

add_executable(tst-wallpaperslideshow-dbus
tst_wallpaperslideshow_dbus.cpp
${WSS_ADAPTOR_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/fakeservice.h
)
target_include_directories(tst-wallpaperslideshow-dbus PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
target_link_libraries(tst-wallpaperslideshow-dbus PRIVATE
Qt6::Core
Qt6::DBus
Qt6::Test
)
add_test(NAME wallpaperslideshow-dbus COMMAND tst-wallpaperslideshow-dbus)

# ---------------------------------------------------------------------------
# xsettings: KeyFile ini/.desktop parser unit test
# ---------------------------------------------------------------------------
add_executable(tst-keyfile
tst_keyfile.cpp
${SRC_DIR}/plugin-qt/xsettings/modules/api/keyfile.cpp
)
target_include_directories(tst-keyfile PRIVATE
${SRC_DIR}/plugin-qt/xsettings/modules/api
)
target_link_libraries(tst-keyfile PRIVATE Qt6::Core Qt6::Test)
add_test(NAME xsettings-keyfile COMMAND tst-keyfile)

# ---------------------------------------------------------------------------
# xsettings: Utils byte-manipulation helper unit test
# ---------------------------------------------------------------------------
add_executable(tst-xsutils
tst_xsutils.cpp
${SRC_DIR}/plugin-qt/xsettings/modules/api/utils.cpp
)
target_include_directories(tst-xsutils PRIVATE
${SRC_DIR}/plugin-qt/xsettings/modules/api
${SRC_DIR}/plugin-qt/xsettings/modules
)
target_link_libraries(tst-xsutils PRIVATE Qt6::Core Qt6::Test)
add_test(NAME xsettings-xsutils COMMAND tst-xsutils)

# ---------------------------------------------------------------------------
# xsettings: XSItemInfo/XSDataInfo marshal/unmarshal unit test
# ---------------------------------------------------------------------------
# Pure byte-serialization layer (XSETTINGS wire format). Depends on the
# already-tested Utils byte helpers; no D-Bus/DConfig/XCB dependencies.
add_executable(tst-xsdatainfo
tst_xsdatainfo.cpp
${SRC_DIR}/plugin-qt/xsettings/impl/xsdatainfo.cpp
${SRC_DIR}/plugin-qt/xsettings/modules/api/utils.cpp
)
target_include_directories(tst-xsdatainfo PRIVATE
${SRC_DIR}/plugin-qt/xsettings/impl
${SRC_DIR}/plugin-qt/xsettings
${SRC_DIR}/plugin-qt/xsettings/modules/api
${SRC_DIR}/plugin-qt/xsettings/modules
)
target_link_libraries(tst-xsdatainfo PRIVATE Qt6::Core Qt6::Test)
add_test(NAME xsettings-xsdatainfo COMMAND tst-xsdatainfo)
54 changes: 54 additions & 0 deletions tests/fakeservice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#ifndef FAKESERVICE_H
#define FAKESERVICE_H

#include <QObject>

Check warning on line 8 in tests/fakeservice.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QObject> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QHash>

Check warning on line 9 in tests/fakeservice.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QHash> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QString>

Check warning on line 10 in tests/fakeservice.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QString> not found. Please note: Cppcheck does not need standard library headers to get proper results.

// Minimal in-process implementation of the org.deepin.dde.WallpaperSlideshow
// D-Bus interface (see
// src/plugin-qt/wallpaperslideshow/org.deepin.dde.WallpaperSlideshow.xml).
//
// It is used by the D-Bus contract test: a WallpaperSlideshowAdaptor (generated
// from the project introspection XML via qt_add_dbus_adaptor) wraps this object
// and publishes it on an isolated session bus, so the test can validate that
// the introspection XML is implementable and that every method/property
// round-trips over a real D-Bus connection — without pulling in the heavy
// SlideshowManager / DConfig / AppearanceDBusProxy dependencies of the
// production WallpaperSlideshow class.
class FakeWallpaperSlideshowService : public QObject
{
Q_OBJECT
Q_PROPERTY(QString WallpaperSlideShow READ wallpaperSlideShow WRITE setWallpaperSlideShow)

public:
explicit FakeWallpaperSlideshowService(QObject *parent = nullptr)
: QObject(parent)
{
}

QString wallpaperSlideShow() const { return m_property; }
void setWallpaperSlideShow(const QString &value) { m_property = value; }

public slots:

Check warning on line 37 in tests/fakeservice.h

View workflow job for this annotation

GitHub Actions / cppcheck

There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it.
void SetWallpaperSlideShow(const QString &monitorName, const QString &slideShow)
{
m_monitors[monitorName] = slideShow;
m_property = slideShow;
}

QString GetWallpaperSlideShow(const QString &monitorName)
{
return m_monitors.value(monitorName);
}

private:
QString m_property;
QHash<QString, QString> m_monitors;
};

#endif // FAKESERVICE_H
104 changes: 104 additions & 0 deletions tests/tst_format.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "format.h"

Check warning on line 5 in tests/tst_format.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "format.h" not found.

#include <QTest>

Check warning on line 7 in tests/tst_format.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QTest> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QImage>

Check warning on line 8 in tests/tst_format.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QImage> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDir>

Check warning on line 9 in tests/tst_format.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDir> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QFile>

Check warning on line 10 in tests/tst_format.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QFile> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QTemporaryDir>

Check warning on line 11 in tests/tst_format.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QTemporaryDir> not found. Please note: Cppcheck does not need standard library headers to get proper results.

// Unit test for FormatPicture::getPictureType (wallpaperslideshow plugin).
// The helper resolves a file's MIME type via QMimeDatabase and maps the
// supported image MIME names to a short type token; unsupported files yield an
// empty string. Fixtures are real images written through QImage::save so the
// MIME detection is content-based and deterministic.
//
// GUI-less: QMimeDatabase / QImage::save do not require a QGuiApplication in
// Qt6 (verified by reviewer's real run). Temp fixtures live in a QTemporaryDir
// so they are removed on scope exit even when a QVERIFY fails mid-test.
class TestFormatPicture : public QObject
{
Q_OBJECT

private slots:
void getPictureType_data();
void getPictureType();
void gifMapsToJpegByActualBehavior();
void unknownFileReturnsEmpty();
};

void TestFormatPicture::getPictureType_data()
{
QTest::addColumn<QString>("format");
QTest::addColumn<QString>("expected");

QTest::newRow("png") << "PNG" << "png";
QTest::newRow("bmp") << "BMP" << "bmp";
QTest::newRow("jpeg") << "JPEG" << "jpeg";
QTest::newRow("tiff") << "TIFF" << "tiff"; // correct map: image/tiff -> "tiff"
}

void TestFormatPicture::getPictureType()
{
QFETCH(QString, format);
QFETCH(QString, expected);

QTemporaryDir dir;
QVERIFY(dir.isValid());
const QString path = dir.filePath(QStringLiteral("img"));

QImage img(1, 1, QImage::Format_RGB32);
img.fill(Qt::black);
if (!img.save(path, format.toLatin1().constData()))
QSKIP("image encoder unavailable on this platform");

QCOMPARE(FormatPicture::getPictureType(path), expected);
// dir removes itself + contents on destruction (RAII)
}

void TestFormatPicture::gifMapsToJpegByActualBehavior()
{
QTemporaryDir dir;
QVERIFY(dir.isValid());
const QString path = dir.filePath(QStringLiteral("img.gif"));

// Qt cannot *write* GIF, so write the minimal GIF89a magic header that
// QMimeDatabase matches for image/gif (the freedesktop magic only checks
// the 6-byte "GIF89a"/"GIF87a" header at offset 0).
QFile f(path);
QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString()));
static const unsigned char gif[] = {
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, // "GIF89a"
0x01, 0x00, 0x01, 0x00, // 1x1 logical screen
0x00, 0x00, 0x00, // no GCT, bg 0, aspect 0
0x3B // trailer
};
QCOMPARE(f.write(reinterpret_cast<const char *>(gif), sizeof(gif)),
qint64(sizeof(gif)));
f.close();

// Defect #4 (recorded, not fixed): typeMap maps image/gif -> "jpeg".
// Assert the *actual* behavior; flip to "gif" once the mapping is fixed.
QCOMPARE(FormatPicture::getPictureType(path), QStringLiteral("jpeg"));
}

void TestFormatPicture::unknownFileReturnsEmpty()
{
QTemporaryDir dir;
QVERIFY(dir.isValid());
const QString path = dir.filePath(QStringLiteral("not_image.txt"));

QFile f(path);
QVERIFY(f.open(QIODevice::WriteOnly));
f.write("not an image\n");
f.close();

QCOMPARE(FormatPicture::getPictureType(path), QString());
}

QTEST_GUILESS_MAIN(TestFormatPicture)

#include "tst_format.moc"
Loading
Loading