From 5cd0c642f59924babe66d017d7c0ced7934de3d3 Mon Sep 17 00:00:00 2001 From: Sebastian Englbrecht Date: Mon, 1 Jun 2026 18:22:54 +0200 Subject: tests: fix or skip tests on windows --- src/tests/dolphinmainwindowtest.cpp | 120 ++++++++++++++++++++++++++++ src/tests/kfileitemlistviewtest.cpp | 6 ++ src/tests/kfileitemmodeltest.cpp | 6 ++ src/tests/kitemlistcontrollerexpandtest.cpp | 6 ++ src/tests/kitemlistcontrollertest.cpp | 6 ++ src/tests/testdir.cpp | 27 +++++-- 6 files changed, 165 insertions(+), 6 deletions(-) diff --git a/src/tests/dolphinmainwindowtest.cpp b/src/tests/dolphinmainwindowtest.cpp index a629268c1..1b036436e 100644 --- a/src/tests/dolphinmainwindowtest.cpp +++ b/src/tests/dolphinmainwindowtest.cpp @@ -209,7 +209,13 @@ void DolphinMainWindowTest::testClosingTabsWithSearchBoxVisible() m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); // Without this call the searchbox doesn't get FocusIn events. +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); auto tabWidget = m_mainWindow->findChild("tabWidget"); @@ -238,7 +244,13 @@ void DolphinMainWindowTest::testActiveViewAfterClosingSplitView() { m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); auto tabWidget = m_mainWindow->findChild("tabWidget"); @@ -283,7 +295,13 @@ void DolphinMainWindowTest::testUpdateWindowTitleAfterClosingSplitView() { m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); auto tabWidget = m_mainWindow->findChild("tabWidget"); @@ -324,7 +342,13 @@ void DolphinMainWindowTest::testUpdateWindowTitleAfterChangingSplitView() { m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); auto tabWidget = m_mainWindow->findChild("tabWidget"); @@ -355,7 +379,13 @@ void DolphinMainWindowTest::testOpenInNewTabTitle() const QUrl homePathUrl{QUrl::fromLocalFile(QDir::homePath())}; m_mainWindow->openDirectories({homePathUrl}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); auto tabWidget = m_mainWindow->findChild("tabWidget"); @@ -386,7 +416,13 @@ void DolphinMainWindowTest::testNewFileMenuEnabled() QFETCH(QUrl, activeViewUrl); m_mainWindow->openDirectories({activeViewUrl}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); auto newFileMenu = m_mainWindow->findChild("new_menu"); @@ -402,7 +438,13 @@ void DolphinMainWindowTest::testCreateFileAction() QString testDirUrl(QDir::cleanPath(testDir->url().toString())); m_mainWindow->openDirectories({testDirUrl}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); QCOMPARE(m_mainWindow->m_activeViewContainer->view()->items().count(), 0); @@ -444,7 +486,13 @@ void DolphinMainWindowTest::testCreateFileActionRequiresWritePermission() m_mainWindow->openDirectories({testDirUrl}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); QTRY_VERIFY_WITH_TIMEOUT(QApplication::activeWindow() != nullptr, 100); @@ -482,7 +530,13 @@ void DolphinMainWindowTest::testWindowTitle() QFETCH(QUrl, activeViewUrl); m_mainWindow->openDirectories({activeViewUrl}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); QFETCH(QString, expectedWindowTitle); @@ -494,7 +548,13 @@ void DolphinMainWindowTest::testFocusLocationBar() const QUrl homePathUrl{QUrl::fromLocalFile(QDir::homePath())}; m_mainWindow->openDirectories({homePathUrl}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); QTRY_VERIFY_WITH_TIMEOUT(QApplication::activeWindow() != nullptr, 100); @@ -524,7 +584,13 @@ void DolphinMainWindowTest::testFocusPlacesPanel() { m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); m_mainWindow->windowHandle()->requestActivate(); QVERIFY(QTest::qWaitForWindowActive(m_mainWindow.data())); @@ -624,7 +690,13 @@ void DolphinMainWindowTest::testPlacesPanelWidthResistance() m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); m_mainWindow->resize(800, m_mainWindow->height()); // make sure the size is sufficient so a places panel resize shouldn't be necessary. +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); QWidget *placesPanel = reinterpret_cast(m_mainWindow->m_placesPanel); @@ -706,7 +778,13 @@ void DolphinMainWindowTest::testGoActions() const QUrl childDirUrl(QDir::cleanPath(testDir->url().toString() + "/b")); m_mainWindow->openDirectories({childDirUrl}, false); // Open "b" dir m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); QVERIFY(!m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Forward))->isEnabled()); @@ -914,7 +992,13 @@ void DolphinMainWindowTest::testAccessibilityTree() { m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); QTRY_VERIFY_WITH_TIMEOUT(QApplication::activeWindow() != nullptr, 100); @@ -999,7 +1083,13 @@ void DolphinMainWindowTest::testAutoSaveSession() { m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); // Create config file @@ -1037,7 +1127,13 @@ void DolphinMainWindowTest::testInlineRename() testDir->createFiles({"aaaa", "bbbb", "cccc", "dddd"}); m_mainWindow->openDirectories({testDir->url()}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); DolphinView *view = m_mainWindow->activeViewContainer()->view(); @@ -1110,7 +1206,13 @@ void DolphinMainWindowTest::testThumbnailAfterRename() m_mainWindow->show(); QVERIFY(viewDirectoryLoadingCompletedSpy.wait()); QVERIFY(previewUpdatedSpy.wait()); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); QTRY_COMPARE(view->m_view->m_visibleItems.count(), view->m_model->count()); // wait for all file widgets to be laid out @@ -1162,7 +1264,13 @@ void DolphinMainWindowTest::testViewModeAfterDynamicView() QSignalSpy modelDirectoryLoadingCompletedSpy(view->m_model, &KFileItemModel::directoryLoadingCompleted); m_mainWindow->show(); QVERIFY(viewDirectoryLoadingCompletedSpy.wait()); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); m_mainWindow->actionCollection()->action(QStringLiteral("details"))->trigger(); QCOMPARE(view->m_mode, DolphinView::DetailsView); @@ -1284,7 +1392,13 @@ void DolphinMainWindowTest::testActivationAndTabTitleAfterRenameOpeningFolder() // Tab 0: Open childDirUrl m_mainWindow->openDirectories({childDirUrl}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); // Tab 0: Enable split view @@ -1358,7 +1472,13 @@ void DolphinMainWindowTest::testActiveViewAfterTabSwitchWithSplitView() { m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); m_mainWindow->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_mainWindow.data())) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); +#endif QVERIFY(m_mainWindow->isVisible()); auto tabWidget = m_mainWindow->findChild("tabWidget"); diff --git a/src/tests/kfileitemlistviewtest.cpp b/src/tests/kfileitemlistviewtest.cpp index 42dc4fc77..3bb66930e 100644 --- a/src/tests/kfileitemlistviewtest.cpp +++ b/src/tests/kfileitemlistviewtest.cpp @@ -51,7 +51,13 @@ void KFileItemListViewTest::init() m_graphicsView = new QGraphicsView(); m_graphicsView->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_graphicsView)) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_graphicsView)); +#endif } void KFileItemListViewTest::cleanup() diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp index bd4a60c09..6583b80f4 100644 --- a/src/tests/kfileitemmodeltest.cpp +++ b/src/tests/kfileitemmodeltest.cpp @@ -673,6 +673,9 @@ void KFileItemModelTest::testExpandItems() void KFileItemModelTest::testExpandParentItems() { +#ifdef Q_OS_WIN + QSKIP("QFileSystemWatcher cannot watch temp directories on Windows CI (access denied)."); +#endif QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted); QSignalSpy loadingCompletedSpy(m_model, &KFileItemModel::directoryLoadingCompleted); QVERIFY(loadingCompletedSpy.isValid()); @@ -759,6 +762,9 @@ void KFileItemModelTest::testExpandParentItems() */ void KFileItemModelTest::testMakeExpandedItemHidden() { +#ifdef Q_OS_WIN + QSKIP("QFileSystemWatcher cannot watch temp directories on Windows CI (access denied)."); +#endif QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted); QSignalSpy itemsRemovedSpy(m_model, &KFileItemModel::itemsRemoved); diff --git a/src/tests/kitemlistcontrollerexpandtest.cpp b/src/tests/kitemlistcontrollerexpandtest.cpp index 06e58fe6b..c95423197 100644 --- a/src/tests/kitemlistcontrollerexpandtest.cpp +++ b/src/tests/kitemlistcontrollerexpandtest.cpp @@ -80,7 +80,13 @@ void KItemListControllerExpandTest::initTestCase() QVERIFY(m_spyDirectoryLoadingCompleted->wait()); m_container->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_container)) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_container)); +#endif } void KItemListControllerExpandTest::cleanupTestCase() { diff --git a/src/tests/kitemlistcontrollertest.cpp b/src/tests/kitemlistcontrollertest.cpp index 2b0e5456d..2125755bb 100644 --- a/src/tests/kitemlistcontrollertest.cpp +++ b/src/tests/kitemlistcontrollertest.cpp @@ -157,7 +157,13 @@ void KItemListControllerTest::initTestCase() QVERIFY(spyDirectoryLoadingCompleted.wait()); m_container->show(); +#ifdef Q_OS_WIN + if (!QTest::qWaitForWindowExposed(m_container)) { + QSKIP("Window not exposed on Windows, probably running in a headless CI environment."); + } +#else QVERIFY(QTest::qWaitForWindowExposed(m_container)); +#endif } void KItemListControllerTest::cleanupTestCase() diff --git a/src/tests/testdir.cpp b/src/tests/testdir.cpp index cd35ac748..84e76e712 100644 --- a/src/tests/testdir.cpp +++ b/src/tests/testdir.cpp @@ -8,8 +8,8 @@ #ifdef Q_OS_UNIX #include -#else -#include +#elif defined(Q_OS_WIN) +#include #endif TestDir::TestDir(const QString &directoryPrefix) @@ -33,10 +33,25 @@ static void setTimeStamp(const QString &path, const QDateTime &mtime) utbuf.modtime = utbuf.actime; utime(QFile::encodeName(path), &utbuf); #elif defined(Q_OS_WIN) - struct _utimbuf utbuf; - utbuf.actime = mtime.toSecsSinceEpoch(); - utbuf.modtime = utbuf.actime; - _wutime(reinterpret_cast(path.utf16()), &utbuf); + HANDLE h = CreateFileW(reinterpret_cast(path.utf16()), + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, // required to open directories + nullptr); + if (h != INVALID_HANDLE_VALUE) { + // Convert a Unix-epoch time in milliseconds to a Windows FILETIME, which + // counts 100-nanosecond intervals since 1601-01-01. + // 11644473600000: milliseconds between 1601-01-01 and the Unix epoch (1970-01-01). + // 10000: 100-nanosecond intervals per millisecond. + qint64 fileTime = (mtime.toMSecsSinceEpoch() + 11644473600000LL) * 10000LL; + FILETIME ft; + ft.dwLowDateTime = static_cast(fileTime & 0xFFFFFFFF); + ft.dwHighDateTime = static_cast((fileTime >> 32) & 0xFFFFFFFF); + SetFileTime(h, nullptr, nullptr, &ft); + CloseHandle(h); + } #endif } -- cgit v1.3.1