diff options
Diffstat (limited to 'tests/auto/corelib/io/qprocess')
81 files changed, 1517 insertions, 1205 deletions
diff --git a/tests/auto/corelib/io/qprocess/BLACKLIST b/tests/auto/corelib/io/qprocess/BLACKLIST deleted file mode 100644 index 682bcbc60c..0000000000 --- a/tests/auto/corelib/io/qprocess/BLACKLIST +++ /dev/null @@ -1,6 +0,0 @@ -[lockupsInStartDetached] -redhatenterpriselinuxworkstation-6.6 -# QTBUG-48455 -[fileWriterProcess] -windows-10 msvc-2017 - diff --git a/tests/auto/corelib/io/qprocess/CMakeLists.txt b/tests/auto/corelib/io/qprocess/CMakeLists.txt new file mode 100644 index 0000000000..17dea9688f --- /dev/null +++ b/tests/auto/corelib/io/qprocess/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(qprocess LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +add_subdirectory(test) +add_subdirectory(testProcessCrash) +add_subdirectory(testProcessEcho) +add_subdirectory(testProcessEcho2) +add_subdirectory(testProcessEcho3) +add_subdirectory(testProcessEnvironment) +add_subdirectory(testProcessHang) +add_subdirectory(testProcessNormal) +add_subdirectory(testProcessOutput) +add_subdirectory(testProcessDeadWhileReading) +add_subdirectory(testProcessEOF) +add_subdirectory(testExitCodes) +add_subdirectory(testForwarding) +add_subdirectory(testForwardingHelper) +if(TARGET Qt::Widgets) + add_subdirectory(testGuiProcess) +endif() +add_subdirectory(testDetached) +add_subdirectory(fileWriterProcess) +add_subdirectory(testSetWorkingDirectory) +add_subdirectory(testSoftExit) +add_subdirectory(testProcessSpacesArgs) +add_subdirectory(testSpaceInName) +if(WIN32) + add_subdirectory(testProcessEchoGui) + add_subdirectory(testSetNamedPipeHandleState) +endif() +if(UNIX) + add_subdirectory(testUnixProcessParameters) +endif() diff --git a/tests/auto/corelib/io/qprocess/crasher.h b/tests/auto/corelib/io/qprocess/crasher.h new file mode 100644 index 0000000000..f1ca82a86b --- /dev/null +++ b/tests/auto/corelib/io/qprocess/crasher.h @@ -0,0 +1,60 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2020 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#if defined(_MSC_VER) +# include <intrin.h> +#endif +#if __has_include(<signal.h>) +# include <signal.h> +#endif +#if __has_include(<sys/resource.h>) +# include <sys/resource.h> +#endif + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +namespace tst_QProcessCrash { +struct NoCoreDumps +{ +#if defined(RLIMIT_CORE) + struct rlimit rlim; + NoCoreDumps() + { + if (getrlimit(RLIMIT_CORE, &rlim) == 0 && rlim.rlim_cur != 0) { + struct rlimit newrlim = rlim; + newrlim.rlim_cur = 0; + setrlimit(RLIMIT_CORE, &newrlim); + } + } + ~NoCoreDumps() + { + setrlimit(RLIMIT_CORE, &rlim); + } +#endif // RLIMIT_CORE +}; + +void crashFallback(volatile int *ptr = nullptr) +{ + *ptr = 0; +} + +void crash() +{ +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + __ud2(); +#elif defined(_MSC_VER) && defined(_M_ARM64) + __debugbreak(); +#elif __has_builtin(__builtin_trap) + __builtin_trap(); +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + asm("ud2"); +#elif defined(SIGILL) + raise(SIGILL); +#endif + + crashFallback(); +} +} // namespace tst_QProcessCrash diff --git a/tests/auto/corelib/io/qprocess/fileWriterProcess/CMakeLists.txt b/tests/auto/corelib/io/qprocess/fileWriterProcess/CMakeLists.txt new file mode 100644 index 0000000000..d431ba2c3f --- /dev/null +++ b/tests/auto/corelib/io/qprocess/fileWriterProcess/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## fileWriterProcess Binary: +##################################################################### + +qt_internal_add_executable(fileWriterProcess + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/fileWriterProcess/fileWriterProcess.pro b/tests/auto/corelib/io/qprocess/fileWriterProcess/fileWriterProcess.pro deleted file mode 100644 index 2744491151..0000000000 --- a/tests/auto/corelib/io/qprocess/fileWriterProcess/fileWriterProcess.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG += cmdline -QT = core -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/fileWriterProcess/main.cpp b/tests/auto/corelib/io/qprocess/fileWriterProcess/main.cpp index efeadadb93..0349a48067 100644 --- a/tests/auto/corelib/io/qprocess/fileWriterProcess/main.cpp +++ b/tests/auto/corelib/io/qprocess/fileWriterProcess/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QCoreApplication> #include <QFile> @@ -34,7 +9,8 @@ int main(int argc, char **argv) { QCoreApplication ca(argc, argv); QFile f; - f.open(stdin, QIODevice::ReadOnly); + if (!f.open(stdin, QIODevice::ReadOnly)) + return 1; QByteArray input; char buf[1024]; qint64 len; diff --git a/tests/auto/corelib/io/qprocess/qprocess.pri b/tests/auto/corelib/io/qprocess/qprocess.pri deleted file mode 100644 index 8d17090545..0000000000 --- a/tests/auto/corelib/io/qprocess/qprocess.pri +++ /dev/null @@ -1,22 +0,0 @@ -SUBPROGRAMS = \ - testProcessCrash \ - testProcessEcho \ - testProcessEcho2 \ - testProcessEcho3 \ - testProcessEnvironment \ - testProcessHang \ - testProcessNormal \ - testProcessOutput \ - testProcessDeadWhileReading \ - testProcessEOF \ - testExitCodes \ - testForwarding \ - testForwardingHelper \ - testGuiProcess \ - testDetached \ - fileWriterProcess \ - testSetWorkingDirectory \ - testSoftExit - -!qtHaveModule(widgets): SUBPROGRAMS -= \ - testGuiProcess diff --git a/tests/auto/corelib/io/qprocess/qprocess.pro b/tests/auto/corelib/io/qprocess/qprocess.pro deleted file mode 100644 index 3867ac5741..0000000000 --- a/tests/auto/corelib/io/qprocess/qprocess.pro +++ /dev/null @@ -1,18 +0,0 @@ -TEMPLATE = subdirs - -include(qprocess.pri) -SUBDIRS = $$SUBPROGRAMS -# Add special cases -SUBDIRS += testProcessSpacesArgs/nospace.pro \ - testProcessSpacesArgs/onespace.pro \ - testProcessSpacesArgs/twospaces.pro \ - testSpaceInName - -win32 { - SUBDIRS += \ - testProcessEchoGui \ - testSetNamedPipeHandleState -} - -test.depends += $$SUBDIRS -SUBDIRS += test diff --git a/tests/auto/corelib/io/qprocess/test/CMakeLists.txt b/tests/auto/corelib/io/qprocess/test/CMakeLists.txt new file mode 100644 index 0000000000..89893583ac --- /dev/null +++ b/tests/auto/corelib/io/qprocess/test/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qprocess Test: +##################################################################### + +qt_internal_add_test(tst_qprocess + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" + SOURCES + ../tst_qprocess.cpp + LIBRARIES + Qt::CorePrivate + Qt::Network + Qt::TestPrivate +) + +## Build assorted sub-programs called from the test: +add_dependencies(tst_qprocess + testProcessCrash + testProcessEcho + testProcessEcho2 + testProcessEcho3 + testProcessEnvironment + testProcessHang + testProcessNormal + testProcessOutput + testProcessDeadWhileReading + testProcessEOF + testExitCodes + testForwarding + testDetached + fileWriterProcess + testSetWorkingDirectory + testSoftExit + nospace onespace twospaces + testSpaceInName +) +if(TARGET Qt::Widgets) + add_dependencies(tst_qprocess testGuiProcess) +endif() +if(WIN32) + add_dependencies(tst_qprocess testProcessEchoGui testSetNamedPipeHandleState) +endif() + +if(UNIX) + add_dependencies(tst_qprocess testUnixProcessParameters) +endif() diff --git a/tests/auto/corelib/io/qprocess/test/test.pro b/tests/auto/corelib/io/qprocess/test/test.pro deleted file mode 100644 index 63187c9668..0000000000 --- a/tests/auto/corelib/io/qprocess/test/test.pro +++ /dev/null @@ -1,22 +0,0 @@ -CONFIG += testcase -CONFIG -= debug_and_release_target -QT = core-private testlib network -SOURCES = ../tst_qprocess.cpp -INCLUDEPATH += ../../../../../shared -HEADERS += ../../../../../shared/emulationdetector.h - -TARGET = ../tst_qprocess - -win32:TESTDATA += ../testBatFiles/* - -include(../qprocess.pri) - -mac:CONFIG += insignificant_test # QTBUG-25895 - sometimes hangs - -for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}" - -TEST_HELPER_INSTALLS += \ - ../testProcessSpacesArgs/nospace \ - "../testProcessSpacesArgs/one space" \ - "../testProcessSpacesArgs/two space s" \ - "../test Space In Name/testSpaceInName" diff --git a/tests/auto/corelib/io/qprocess/testBatFiles/simple.bat b/tests/auto/corelib/io/qprocess/testBatFiles/simple.bat index 900f7ae356..8567e16850 100755 --- a/tests/auto/corelib/io/qprocess/testBatFiles/simple.bat +++ b/tests/auto/corelib/io/qprocess/testBatFiles/simple.bat @@ -1,2 +1,4 @@ +:: Copyright (C) 2024 The Qt Company Ltd. +:: SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 @echo off -echo Hello
\ No newline at end of file +echo Hello diff --git a/tests/auto/corelib/io/qprocess/testBatFiles/with space.bat b/tests/auto/corelib/io/qprocess/testBatFiles/with space.bat index 900f7ae356..8567e16850 100755 --- a/tests/auto/corelib/io/qprocess/testBatFiles/with space.bat +++ b/tests/auto/corelib/io/qprocess/testBatFiles/with space.bat @@ -1,2 +1,4 @@ +:: Copyright (C) 2024 The Qt Company Ltd. +:: SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 @echo off -echo Hello
\ No newline at end of file +echo Hello diff --git a/tests/auto/corelib/io/qprocess/testDetached/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testDetached/CMakeLists.txt new file mode 100644 index 0000000000..2439fc67a7 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testDetached/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testDetached Binary: +##################################################################### + +qt_internal_add_executable(testDetached + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testDetached/main.cpp b/tests/auto/corelib/io/qprocess/testDetached/main.cpp index c10e32d584..9b0b3855a0 100644 --- a/tests/auto/corelib/io/qprocess/testDetached/main.cpp +++ b/tests/auto/corelib/io/qprocess/testDetached/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QCoreApplication> #include <QDebug> #include <QStringList> @@ -66,7 +41,7 @@ struct Args static Args parseArguments(const QStringList &args) { Args result; - if (args.count() < 2) { + if (args.size() < 2) { result.exitCode = 128; result.errorMessage = "Usage: testDetached [--out-channel={stdout|stderr}] filename.txt\n"; return result; diff --git a/tests/auto/corelib/io/qprocess/testDetached/testDetached.pro b/tests/auto/corelib/io/qprocess/testDetached/testDetached.pro deleted file mode 100644 index 3d80b668df..0000000000 --- a/tests/auto/corelib/io/qprocess/testDetached/testDetached.pro +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES = main.cpp -QT = core -CONFIG += cmdline -INSTALLS = -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testExitCodes/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testExitCodes/CMakeLists.txt new file mode 100644 index 0000000000..bc03f52d00 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testExitCodes/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testExitCodes Binary: +##################################################################### + +qt_internal_add_executable(testExitCodes + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testExitCodes/main.cpp b/tests/auto/corelib/io/qprocess/testExitCodes/main.cpp index f681870609..3f186d2272 100644 --- a/tests/auto/corelib/io/qprocess/testExitCodes/main.cpp +++ b/tests/auto/corelib/io/qprocess/testExitCodes/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdlib.h> diff --git a/tests/auto/corelib/io/qprocess/testExitCodes/testExitCodes.pro b/tests/auto/corelib/io/qprocess/testExitCodes/testExitCodes.pro deleted file mode 100644 index 5eaf8dc881..0000000000 --- a/tests/auto/corelib/io/qprocess/testExitCodes/testExitCodes.pro +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES += main.cpp -CONFIG -= qt -CONFIG += cmdline - -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testForwarding/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testForwarding/CMakeLists.txt new file mode 100644 index 0000000000..77739d2c68 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testForwarding/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testForwarding Binary: +##################################################################### + +qt_internal_add_executable(testForwarding + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + SOURCES + main.cpp +) + +add_dependencies(testForwarding testForwardingHelper) diff --git a/tests/auto/corelib/io/qprocess/testForwarding/main.cpp b/tests/auto/corelib/io/qprocess/testForwarding/main.cpp index b5d56a1138..774a8622e1 100644 --- a/tests/auto/corelib/io/qprocess/testForwarding/main.cpp +++ b/tests/auto/corelib/io/qprocess/testForwarding/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/QCoreApplication> #include <QtCore/QDeadlineTimer> @@ -38,7 +13,7 @@ static bool waitForDoneFileWritten(const QString &filePath, int msecs = 30000) { QDeadlineTimer t(msecs); do { - QThread::msleep(250); + QThread::sleep(std::chrono::milliseconds{250}); QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) continue; diff --git a/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro b/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro deleted file mode 100644 index 4d91e0cf36..0000000000 --- a/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG += cmdline -DESTDIR = ./ -QT = core diff --git a/tests/auto/corelib/io/qprocess/testForwardingHelper/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testForwardingHelper/CMakeLists.txt new file mode 100644 index 0000000000..9f5f064307 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testForwardingHelper/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testForwardingHelper Binary: +##################################################################### + +qt_internal_add_executable(testForwardingHelper + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testForwardingHelper/main.cpp b/tests/auto/corelib/io/qprocess/testForwardingHelper/main.cpp index 682ca7346b..4b4d9d4715 100644 --- a/tests/auto/corelib/io/qprocess/testForwardingHelper/main.cpp +++ b/tests/auto/corelib/io/qprocess/testForwardingHelper/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <fstream> #include <stdio.h> @@ -36,8 +11,8 @@ int main(int argc, char *argv[]) return 1; } fputs("out data", stdout); - fputs("err data", stderr); fflush(stdout); + fputs("err data", stderr); fflush(stderr); std::ofstream out(argv[1]); out << "That's all folks!"; diff --git a/tests/auto/corelib/io/qprocess/testForwardingHelper/testForwardingHelper.pro b/tests/auto/corelib/io/qprocess/testForwardingHelper/testForwardingHelper.pro deleted file mode 100644 index 6a23e52d95..0000000000 --- a/tests/auto/corelib/io/qprocess/testForwardingHelper/testForwardingHelper.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testGuiProcess/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testGuiProcess/CMakeLists.txt new file mode 100644 index 0000000000..781f49e515 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testGuiProcess/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testGuiProcess Binary: +##################################################################### + +qt_internal_add_executable(testGuiProcess + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + SOURCES + main.cpp + LIBRARIES + Qt::Gui + Qt::Widgets +) diff --git a/tests/auto/corelib/io/qprocess/testGuiProcess/main.cpp b/tests/auto/corelib/io/qprocess/testGuiProcess/main.cpp index 98babfacb8..1c65268511 100644 --- a/tests/auto/corelib/io/qprocess/testGuiProcess/main.cpp +++ b/tests/auto/corelib/io/qprocess/testGuiProcess/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testGuiProcess/testGuiProcess.pro b/tests/auto/corelib/io/qprocess/testGuiProcess/testGuiProcess.pro deleted file mode 100644 index ef438d6399..0000000000 --- a/tests/auto/corelib/io/qprocess/testGuiProcess/testGuiProcess.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES += main.cpp -QT += widgets -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessCrash/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessCrash/CMakeLists.txt new file mode 100644 index 0000000000..2f167899eb --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessCrash/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessCrash Binary: +##################################################################### + +qt_internal_add_executable(testProcessCrash + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessCrash/main.cpp b/tests/auto/corelib/io/qprocess/testProcessCrash/main.cpp index 262db73d72..a5f1eef88a 100644 --- a/tests/auto/corelib/io/qprocess/testProcessCrash/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessCrash/main.cpp @@ -1,40 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2020 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -struct Foo -{ - int i; -}; +#include "../crasher.h" +using namespace tst_QProcessCrash; int main() { - *(volatile char*)0 = 0; - Foo *f = 0; - return f->i; + [[maybe_unused]] // NoCoreDumps may be an empty struct, not a RAII class + NoCoreDumps disableCoreDumps; + crash(); + return 0; } diff --git a/tests/auto/corelib/io/qprocess/testProcessCrash/testProcessCrash.pro b/tests/auto/corelib/io/qprocess/testProcessCrash/testProcessCrash.pro deleted file mode 100644 index 640ce4cd09..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessCrash/testProcessCrash.pro +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES = main.cpp -CONFIG += cmdline -CONFIG -= qt - -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/CMakeLists.txt new file mode 100644 index 0000000000..bdd82c6419 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessDeadWhileReading Binary: +##################################################################### + +qt_internal_add_executable(testProcessDeadWhileReading + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/main.cpp b/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/main.cpp index eb780fbc3a..0add9d56de 100644 --- a/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/testProcessDeadWhileReading.pro b/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/testProcessDeadWhileReading.pro deleted file mode 100644 index c7be60a82d..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessDeadWhileReading/testProcessDeadWhileReading.pro +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline - -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessEOF/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessEOF/CMakeLists.txt new file mode 100644 index 0000000000..8914bf181d --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessEOF/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessEOF Binary: +##################################################################### + +qt_internal_add_executable(testProcessEOF + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessEOF/main.cpp b/tests/auto/corelib/io/qprocess/testProcessEOF/main.cpp index 4fb2e29c2d..a0efdbd271 100644 --- a/tests/auto/corelib/io/qprocess/testProcessEOF/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessEOF/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessEOF/testProcessEOF.pro b/tests/auto/corelib/io/qprocess/testProcessEOF/testProcessEOF.pro deleted file mode 100644 index 6a23e52d95..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessEOF/testProcessEOF.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessEcho/CMakeLists.txt new file mode 100644 index 0000000000..071156f759 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessEcho/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessEcho Binary: +##################################################################### + +qt_internal_add_executable(testProcessEcho + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho/main.cpp b/tests/auto/corelib/io/qprocess/testProcessEcho/main.cpp index e18e48e516..7b87380900 100644 --- a/tests/auto/corelib/io/qprocess/testProcessEcho/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessEcho/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho/testProcessEcho.pro b/tests/auto/corelib/io/qprocess/testProcessEcho/testProcessEcho.pro deleted file mode 100644 index 6a23e52d95..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessEcho/testProcessEcho.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho2/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessEcho2/CMakeLists.txt new file mode 100644 index 0000000000..9f71b1ebb6 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessEcho2/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessEcho2 Binary: +##################################################################### + +qt_internal_add_executable(testProcessEcho2 + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho2/main.cpp b/tests/auto/corelib/io/qprocess/testProcessEcho2/main.cpp index ce4494b048..b67480e6bb 100644 --- a/tests/auto/corelib/io/qprocess/testProcessEcho2/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessEcho2/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho2/testProcessEcho2.pro b/tests/auto/corelib/io/qprocess/testProcessEcho2/testProcessEcho2.pro deleted file mode 100644 index 6a23e52d95..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessEcho2/testProcessEcho2.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho3/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessEcho3/CMakeLists.txt new file mode 100644 index 0000000000..badc9ef82d --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessEcho3/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessEcho3 Binary: +##################################################################### + +qt_internal_add_executable(testProcessEcho3 + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho3/main.cpp b/tests/auto/corelib/io/qprocess/testProcessEcho3/main.cpp index dfd6e009db..161f8bd547 100644 --- a/tests/auto/corelib/io/qprocess/testProcessEcho3/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessEcho3/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessEcho3/testProcessEcho3.pro b/tests/auto/corelib/io/qprocess/testProcessEcho3/testProcessEcho3.pro deleted file mode 100644 index 6a23e52d95..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessEcho3/testProcessEcho3.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessEchoGui/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessEchoGui/CMakeLists.txt new file mode 100644 index 0000000000..43663e62e8 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessEchoGui/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessEchoGui Binary: +##################################################################### + +qt_internal_add_executable(testProcessEchoGui + GUI + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main_win.cpp +) +target_link_libraries(testProcessEchoGui PRIVATE user32) diff --git a/tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp b/tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp index abe957c1ea..ab54e4a328 100644 --- a/tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <windows.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro b/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro deleted file mode 100644 index e41ed0a425..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro +++ /dev/null @@ -1,8 +0,0 @@ -win32 { - SOURCES = main_win.cpp - QMAKE_USE += user32 -} - -CONFIG -= qt app_bundle -DESTDIR = ./ -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/io/qprocess/testProcessEnvironment/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessEnvironment/CMakeLists.txt new file mode 100644 index 0000000000..9069bbc7c8 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessEnvironment/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessEnvironment Binary: +##################################################################### + +qt_internal_add_executable(testProcessEnvironment + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessEnvironment/main.cpp b/tests/auto/corelib/io/qprocess/testProcessEnvironment/main.cpp index 9f13f5c00f..dae98c3af6 100644 --- a/tests/auto/corelib/io/qprocess/testProcessEnvironment/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessEnvironment/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> #include <stdlib.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessEnvironment/testProcessEnvironment.pro b/tests/auto/corelib/io/qprocess/testProcessEnvironment/testProcessEnvironment.pro deleted file mode 100644 index 6a23e52d95..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessEnvironment/testProcessEnvironment.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessHang/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessHang/CMakeLists.txt new file mode 100644 index 0000000000..cb6f490c40 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessHang/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessHang Binary: +##################################################################### + +qt_internal_add_executable(testProcessHang + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessHang/main.cpp b/tests/auto/corelib/io/qprocess/testProcessHang/main.cpp index cb904134f9..89fcadfb8f 100644 --- a/tests/auto/corelib/io/qprocess/testProcessHang/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessHang/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessHang/testProcessHang.pro b/tests/auto/corelib/io/qprocess/testProcessHang/testProcessHang.pro deleted file mode 100644 index 6a23e52d95..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessHang/testProcessHang.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testProcessNormal/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessNormal/CMakeLists.txt new file mode 100644 index 0000000000..7eb6388792 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessNormal/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessNormal Binary: +##################################################################### + +qt_internal_add_executable(testProcessNormal + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessNormal/main.cpp b/tests/auto/corelib/io/qprocess/testProcessNormal/main.cpp index 4611ed4547..a714713cf2 100644 --- a/tests/auto/corelib/io/qprocess/testProcessNormal/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessNormal/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only int main() diff --git a/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro b/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro deleted file mode 100644 index 7e1119c117..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro +++ /dev/null @@ -1,6 +0,0 @@ -SOURCES = main.cpp -CONFIG += cmdline -CONFIG -= qt - -DESTDIR = ./ -QT = core diff --git a/tests/auto/corelib/io/qprocess/testProcessOutput/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessOutput/CMakeLists.txt new file mode 100644 index 0000000000..78005b2b93 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessOutput/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessOutput Binary: +##################################################################### + +qt_internal_add_executable(testProcessOutput + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testProcessOutput/main.cpp b/tests/auto/corelib/io/qprocess/testProcessOutput/main.cpp index 4934708153..08d059e0f9 100644 --- a/tests/auto/corelib/io/qprocess/testProcessOutput/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessOutput/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro b/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro deleted file mode 100644 index 0bbb6b3c0e..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ -QT = core diff --git a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/CMakeLists.txt new file mode 100644 index 0000000000..5ea7bf53f4 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_executable(nospace + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) + +qt_internal_add_executable(onespace + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) +set_target_properties(onespace PROPERTIES OUTPUT_NAME "one space") + +qt_internal_add_executable(twospaces + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) +set_target_properties(twospaces PROPERTIES OUTPUT_NAME "two space s") diff --git a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/main.cpp b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/main.cpp index 0d40a9b83c..2c319fa9af 100644 --- a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/main.cpp +++ b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/nospace.pro b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/nospace.pro deleted file mode 100644 index 7954a2f74b..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/nospace.pro +++ /dev/null @@ -1,6 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ -OBJECTS_DIR = $${OBJECTS_DIR}-nospace -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/onespace.pro b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/onespace.pro deleted file mode 100644 index 44a365c9a5..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/onespace.pro +++ /dev/null @@ -1,8 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ -OBJECTS_DIR = $${OBJECTS_DIR}-onespace - -TARGET = "one space" -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro deleted file mode 100644 index bd2db9fb6d..0000000000 --- a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro +++ /dev/null @@ -1,9 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ -OBJECTS_DIR = $${OBJECTS_DIR}-twospaces - -TARGET = "two space s" -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 -QT = core diff --git a/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/CMakeLists.txt new file mode 100644 index 0000000000..5e532aa017 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testSetNamedPipeHandleState Binary: +##################################################################### + +qt_internal_add_executable(testSetNamedPipeHandleState + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) +target_link_libraries(testSetNamedPipeHandleState PRIVATE kernel32.lib) diff --git a/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/main.cpp b/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/main.cpp index 488b03ab57..ace55e9058 100644 --- a/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/main.cpp +++ b/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <windows.h> diff --git a/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/testSetNamedPipeHandleState.pro b/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/testSetNamedPipeHandleState.pro deleted file mode 100644 index 6a23e52d95..0000000000 --- a/tests/auto/corelib/io/qprocess/testSetNamedPipeHandleState/testSetNamedPipeHandleState.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ diff --git a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/CMakeLists.txt new file mode 100644 index 0000000000..f5b9c22c90 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testSetWorkingDirectory Binary: +##################################################################### + +qt_internal_add_executable(testSetWorkingDirectory + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/main.cpp b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/main.cpp index 37d7deb1ac..c12ca2de7a 100644 --- a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/main.cpp +++ b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QCoreApplication> diff --git a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro deleted file mode 100644 index 4d91e0cf36..0000000000 --- a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES = main.cpp -CONFIG += cmdline -DESTDIR = ./ -QT = core diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testSoftExit/CMakeLists.txt new file mode 100644 index 0000000000..44099dcab1 --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testSoftExit/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testSoftExit Binary: +##################################################################### + +qt_internal_add_executable(testSoftExit + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None +) + +qt_internal_extend_target(testSoftExit CONDITION WIN32 + SOURCES + main_win.cpp + LIBRARIES + user32 +) + +qt_internal_extend_target(testSoftExit CONDITION UNIX + SOURCES + main_unix.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp b/tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp index ed0f16ac17..6d5078e75e 100644 --- a/tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp +++ b/tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <sys/types.h> diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp b/tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp index 898029483f..cbef8418e6 100644 --- a/tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp +++ b/tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <windows.h> diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro deleted file mode 100644 index 964c47f6ae..0000000000 --- a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro +++ /dev/null @@ -1,12 +0,0 @@ -win32 { - SOURCES = main_win.cpp - QMAKE_USE += user32 -} -unix { - SOURCES = main_unix.cpp -} - -CONFIG -= qt -CONFIG += cmdline -DESTDIR = ./ -QT = core diff --git a/tests/auto/corelib/io/qprocess/testSpaceInName/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testSpaceInName/CMakeLists.txt new file mode 100644 index 0000000000..9cc05bfc3d --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testSpaceInName/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testSpaceInName Binary: +##################################################################### + +qt_internal_add_executable(testSpaceInName + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) +set_property(TARGET testSpaceInName PROPERTY + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../test Space In Name") diff --git a/tests/auto/corelib/io/qprocess/testSpaceInName/main.cpp b/tests/auto/corelib/io/qprocess/testSpaceInName/main.cpp index 0e2374de06..ca54a6bfde 100644 --- a/tests/auto/corelib/io/qprocess/testSpaceInName/main.cpp +++ b/tests/auto/corelib/io/qprocess/testSpaceInName/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <stdio.h> diff --git a/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro b/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro deleted file mode 100644 index 48f28c4c8b..0000000000 --- a/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES = main.cpp -CONFIG -= qt -CONFIG += cmdline -DESTDIR = "../test Space In Name" -QT = core diff --git a/tests/auto/corelib/io/qprocess/testUnixProcessParameters/CMakeLists.txt b/tests/auto/corelib/io/qprocess/testUnixProcessParameters/CMakeLists.txt new file mode 100644 index 0000000000..9b6c48933c --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testUnixProcessParameters/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2023 Intel Corporation. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## testProcessNormal Binary: +##################################################################### + +qt_internal_add_executable(testUnixProcessParameters + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + CORE_LIBRARY None + SOURCES + main.cpp +) diff --git a/tests/auto/corelib/io/qprocess/testUnixProcessParameters/main.cpp b/tests/auto/corelib/io/qprocess/testUnixProcessParameters/main.cpp new file mode 100644 index 0000000000..42a173debe --- /dev/null +++ b/tests/auto/corelib/io/qprocess/testUnixProcessParameters/main.cpp @@ -0,0 +1,109 @@ +// Copyright (C) 2023 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <string_view> + +#include <errno.h> +#include <fcntl.h> +#include <sched.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/resource.h> +#include <unistd.h> + +int main(int argc, char **argv) +{ + if (argc < 2) { + printf("Usage: %s command [extra]\nSee source code for commands\n", + argv[0]); + return EXIT_FAILURE; + } + + std::string_view cmd = argv[1]; + errno = 0; + + if (cmd.size() == 0) { + // just checking that we did get here + return EXIT_SUCCESS; + } + + if (cmd == "reset-ids") { + if (getuid() == geteuid() && getgid() == getegid()) + return EXIT_SUCCESS; + fprintf(stderr, "Real: %d %d; Effective: %d %d\n", + getuid(), getgid(), geteuid(), getegid()); + return EXIT_FAILURE; + } + + if (cmd == "reset-sighand") { + bool ok = true; + + // confirm our signal block mask is empty + sigset_t set; + sigprocmask(SIG_SETMASK, nullptr, &set); + for (int signo = 1; signo < NSIG; ++signo) { + if (sigismember(&set, signo)) { + fprintf(stderr, "'%s' is blocked.\n", strsignal(signo)); + ok = false; + } + } + + // confirm SIGUSR1 was not ignored + struct sigaction action; + sigaction(SIGUSR1, nullptr, &action); + if (action.sa_handler != SIG_DFL) { + fprintf(stderr, "SIGUSR1 is SIG_IGN\n"); + ok = false; + } + return ok ? EXIT_SUCCESS : EXIT_FAILURE; + } + + if (cmd == "ignore-sigpipe") { + // confirm SIGPIPE was ignored + struct sigaction action; + sigaction(SIGPIPE, nullptr, &action); + if (action.sa_handler == SIG_IGN) + return EXIT_SUCCESS; + fprintf(stderr, "SIGPIPE is SIG_DFL\n"); + return EXIT_FAILURE; + } + + if (cmd == "file-descriptors") { + int fd = atoi(argv[2]); + if (close(fd) < 0 && errno == EBADF) + return EXIT_SUCCESS; + fprintf(stderr, "%d is a valid file descriptor\n", fd); + return EXIT_FAILURE; + } + + if (cmd == "file-descriptors2") { + int fd1 = atoi(argv[2]); // should be open + int fd2 = atoi(argv[3]); // should be closed + if (close(fd1) < 0) + fprintf(stderr, "%d was not a valid file descriptor\n", fd1); + if (close(fd2) == 0 || errno != EBADF) + fprintf(stderr, "%d is a valid file descriptor\n", fd2); + return EXIT_SUCCESS; + } + + if (cmd == "noctty") { + int fd = open("/dev/tty", O_RDONLY); + if (fd == -1) + return EXIT_SUCCESS; + fprintf(stderr, "Could open /dev/tty\n"); + return EXIT_FAILURE; + } + + if (cmd == "setsid") { + pid_t pgid = getpgrp(); + if (pgid == getpid()) + return EXIT_SUCCESS; + fprintf(stderr, "Process group was %d\n", pgid); + return EXIT_FAILURE; + } + + fprintf(stderr, "Unknown command \"%s\"", cmd.data()); + return EXIT_FAILURE; +} diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index e799369c8a..5f35732979 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -1,49 +1,37 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <emulationdetector.h> - -#include <QtTest/QtTest> +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2022 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> +#include <QTestEventLoop> +#include <QSignalSpy> + #include <QtCore/QProcess> #include <QtCore/QDir> #include <QtCore/QElapsedTimer> #include <QtCore/QFile> #include <QtCore/QThread> #include <QtCore/QTemporaryDir> -#include <QtCore/QRegExp> +#include <QtCore/QRegularExpression> #include <QtCore/QDebug> #include <QtCore/QMetaType> +#include <QtCore/QScopeGuard> #include <QtNetwork/QHostInfo> + +#include <qplatformdefs.h> +#ifdef Q_OS_UNIX +# include <private/qcore_unix_p.h> +# include <sys/wait.h> +#endif + +#include <QtTest/private/qemulationdetector_p.h> + #include <stdlib.h> -typedef void (QProcess::*QProcessFinishedSignal1)(int); -typedef void (QProcess::*QProcessFinishedSignal2)(int, QProcess::ExitStatus); +#include "crasher.h" + +using namespace Qt::StringLiterals; + typedef void (QProcess::*QProcessErrorSignal)(QProcess::ProcessError); class tst_QProcess : public QObject @@ -59,6 +47,8 @@ private slots: void getSetCheck(); void constructing(); void simpleStart(); + void startCommand(); + void startCommandEmptyString(); void startWithOpen(); void startWithOldOpen(); void execute(); @@ -99,8 +89,11 @@ private slots: void environmentIsSorted(); void spaceInName(); void setStandardInputFile(); + void setStandardInputFileFailure(); void setStandardOutputFile_data(); void setStandardOutputFile(); + void setStandardOutputFileFailure_data() { setStandardOutputFile_data(); } + void setStandardOutputFileFailure(); void setStandardOutputFileNullDevice(); void setStandardOutputFileAndWaitForBytesWritten(); void setStandardOutputProcess_data(); @@ -111,6 +104,7 @@ private slots: void discardUnwantedOutput(); void setWorkingDirectory(); void setNonExistentWorkingDirectory(); + void detachedSetNonExistentWorkingDirectory(); void exitStatus_data(); void exitStatus(); @@ -125,6 +119,22 @@ private slots: void nativeArguments(); void createProcessArgumentsModifier(); #endif // Q_OS_WIN +#if defined(Q_OS_UNIX) + void setChildProcessModifier_data(); + void setChildProcessModifier(); + void failChildProcessModifier_data() { setChildProcessModifier_data(); } + void failChildProcessModifier(); + void throwInChildProcessModifier(); + void terminateInChildProcessModifier_data(); + void terminateInChildProcessModifier(); + void raiseInChildProcessModifier(); + void unixProcessParameters_data(); + void unixProcessParameters(); + void impossibleUnixProcessParameters_data(); + void impossibleUnixProcessParameters(); + void unixProcessParametersAndChildModifier(); + void unixProcessParametersOtherFileDescriptors(); +#endif void exitCodeTest(); void systemEnvironment(); void lockupsInStartDetached(); @@ -142,6 +152,8 @@ private slots: void startStopStartStopBuffers(); void processEventsInAReadyReadSlot_data(); void processEventsInAReadyReadSlot(); + void startFromCurrentWorkingDir_data(); + void startFromCurrentWorkingDir(); // keep these at the end, since they use lots of processes and sometimes // caused obscure failures to occur in tests that followed them (esp. on the Mac) @@ -151,13 +163,6 @@ private slots: void failToStartEmptyArgs_data(); void failToStartEmptyArgs(); -#if QT_DEPRECATED_SINCE(5, 13) - void crashTest2_deprecated(); - void restartProcessDeadlock_deprecated(); - void waitForReadyReadInAReadyReadSlot_deprecated(); - void finishProcessBeforeReadingDone_deprecated(); -#endif - protected slots: void readFromProcess(); void exitLoopSlot(); @@ -167,16 +172,28 @@ protected slots: void waitForBytesWrittenInABytesWrittenSlotSlot(); private: + QString nonExistentFileName = u"/this/file/cant/exist/hopefully"_s; + qint64 bytesAvailable; QTemporaryDir m_temporaryDir; + bool haveWorkingVFork = false; }; void tst_QProcess::initTestCase() { +#if defined(QT_ASAN_ENABLED) + QSKIP("Skipping QProcess tests under ASAN as they are flaky (QTBUG-109329)"); +#endif QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); // chdir to our testdata path and execute helper apps relative to that. QString testdata_dir = QFileInfo(QFINDTESTDATA("testProcessNormal")).absolutePath(); QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir)); + +#if defined(Q_OS_LINUX) && QT_CONFIG(forkfd_pidfd) + // see detect_clone_pidfd_support() in forkfd_linux.c for explanation + waitid(/*P_PIDFD*/ idtype_t(3), INT_MAX, NULL, WEXITED|WNOHANG); + haveWorkingVFork = (errno == EBADF); +#endif } void tst_QProcess::cleanupTestCase() @@ -194,14 +211,6 @@ void tst_QProcess::getSetCheck() QProcess obj1; // ProcessChannelMode QProcess::readChannelMode() // void QProcess::setProcessChannelMode(ProcessChannelMode) -#if QT_DEPRECATED_SINCE(5, 13) - obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::SeparateChannels)); - QCOMPARE(QProcess::ProcessChannelMode(QProcess::SeparateChannels), obj1.readChannelMode()); - obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::MergedChannels)); - QCOMPARE(QProcess::ProcessChannelMode(QProcess::MergedChannels), obj1.readChannelMode()); - obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::ForwardedChannels)); - QCOMPARE(QProcess::ProcessChannelMode(QProcess::ForwardedChannels), obj1.readChannelMode()); -#endif obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::SeparateChannels)); QCOMPARE(QProcess::ProcessChannelMode(QProcess::SeparateChannels), obj1.processChannelMode()); obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::MergedChannels)); @@ -225,7 +234,7 @@ void tst_QProcess::constructing() QCOMPARE(process.environment(), QStringList()); QCOMPARE(process.error(), QProcess::UnknownError); QCOMPARE(process.state(), QProcess::NotRunning); - QCOMPARE(process.pid(), Q_PID(0)); + QCOMPARE(process.processId(), 0); QCOMPARE(process.readAllStandardOutput(), QByteArray()); QCOMPARE(process.readAllStandardError(), QByteArray()); QCOMPARE(process.canReadLine(), false); @@ -271,12 +280,45 @@ void tst_QProcess::simpleStart() process.reset(); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); QCOMPARE(qvariant_cast<QProcess::ProcessState>(spy.at(0).at(0)), QProcess::Starting); QCOMPARE(qvariant_cast<QProcess::ProcessState>(spy.at(1).at(0)), QProcess::Running); QCOMPARE(qvariant_cast<QProcess::ProcessState>(spy.at(2).at(0)), QProcess::NotRunning); } +void tst_QProcess::startCommand() +{ + QProcess process; + process.startCommand("testProcessSpacesArgs/nospace foo \"b a r\" baz"); + QVERIFY2(process.waitForStarted(), qPrintable(process.errorString())); + QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); + QByteArray actual = process.readAll(); + actual.remove(0, actual.indexOf('|') + 1); + QByteArray expected = "foo|b a r|baz"; + QCOMPARE(actual, expected); +} + +void tst_QProcess::startCommandEmptyString() +{ + static const char warningMsg[] = + "QProcess::startCommand: empty or whitespace-only command was provided"; + QProcess process; + + QTest::ignoreMessage(QtWarningMsg, warningMsg); + process.startCommand(""); + QVERIFY(!process.waitForStarted()); + + QTest::ignoreMessage(QtWarningMsg, warningMsg); + process.startCommand(" "); + QVERIFY(!process.waitForStarted()); + + QTest::ignoreMessage(QtWarningMsg, warningMsg); + process.startCommand("\t\n"); + QVERIFY(!process.waitForStarted()); +} + void tst_QProcess::startWithOpen() { QProcess p; @@ -330,9 +372,7 @@ void tst_QProcess::readFromProcess() { QProcess *process = qobject_cast<QProcess *>(sender()); QVERIFY(process); - int lines = 0; while (process->canReadLine()) { - ++lines; process->readLine(); } } @@ -350,34 +390,24 @@ void tst_QProcess::crashTest() qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus"); QSignalSpy spy(process.data(), &QProcess::errorOccurred); - QSignalSpy spy2(process.data(), static_cast<QProcessFinishedSignal2>(&QProcess::finished)); + QSignalSpy spy2(process.data(), &QProcess::finished); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); -#if QT_DEPRECATED_SINCE(5, 6) - QSignalSpy spy3(process.data(), static_cast<QProcessErrorSignal>(&QProcess::error)); - QVERIFY(spy3.isValid()); -#endif - QVERIFY(process->waitForFinished(30000)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed); - QCOMPARE(spy2.count(), 1); + QCOMPARE(spy2.size(), 1); QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(spy3.count(), 1); - QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy3.at(0).at(0).constData()), QProcess::Crashed); -#endif - QCOMPARE(process->exitStatus(), QProcess::CrashExit); // delete process; process.reset(); - QCOMPARE(stateSpy.count(), 3); + QCOMPARE(stateSpy.size(), 3); QCOMPARE(qvariant_cast<QProcess::ProcessState>(stateSpy.at(0).at(0)), QProcess::Starting); QCOMPARE(qvariant_cast<QProcess::ProcessState>(stateSpy.at(1).at(0)), QProcess::Running); QCOMPARE(qvariant_cast<QProcess::ProcessState>(stateSpy.at(2).at(0)), QProcess::NotRunning); @@ -393,22 +423,21 @@ void tst_QProcess::crashTest2() qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus"); QSignalSpy spy(&process, static_cast<QProcessErrorSignal>(&QProcess::errorOccurred)); - QSignalSpy spy2(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished)); + QSignalSpy spy2(&process, &QProcess::finished); QVERIFY(spy.isValid()); QVERIFY(spy2.isValid()); - QObject::connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished), - this, &tst_QProcess::exitLoopSlot); + QObject::connect(&process, &QProcess::finished, this, &tst_QProcess::exitLoopSlot); QTestEventLoop::instance().enterLoop(30); if (QTestEventLoop::instance().timeout()) QFAIL("Failed to detect crash : operation timed out"); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed); - QCOMPARE(spy2.count(), 1); + QCOMPARE(spy2.size(), 1); QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit); QCOMPARE(process.exitStatus(), QProcess::CrashExit); @@ -514,9 +543,9 @@ void tst_QProcess::echoTest2() break; } - QVERIFY(spy0.count() > 0); - QVERIFY(spy1.count() > 0); - QVERIFY(spy2.count() > 0); + QVERIFY(spy0.size() > 0); + QVERIFY(spy1.size() > 0); + QVERIFY(spy2.size() > 0); QCOMPARE(process.readAllStandardOutput(), QByteArray("Hello")); QCOMPARE(process.readAllStandardError(), QByteArray("Hello")); @@ -617,8 +646,8 @@ void tst_QProcess::exitStatus() QFETCH(QStringList, processList); QFETCH(QList<QProcess::ExitStatus>, exitStatus); - QCOMPARE(exitStatus.count(), processList.count()); - for (int i = 0; i < processList.count(); ++i) { + QCOMPARE(exitStatus.size(), processList.size()); + for (int i = 0; i < processList.size(); ++i) { process.start(processList.at(i)); QVERIFY(process.waitForStarted(5000)); QVERIFY(process.waitForFinished(30000)); @@ -665,22 +694,14 @@ void tst_QProcess::readTimeoutAndThenCrash() qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); QSignalSpy spy(&process, &QProcess::errorOccurred); QVERIFY(spy.isValid()); -#if QT_DEPRECATED_SINCE(5, 6) - QSignalSpy spy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error)); - QVERIFY(spy2.isValid()); -#endif process.kill(); QVERIFY(process.waitForFinished(5000)); QCOMPARE(process.state(), QProcess::NotRunning); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(spy2.count(), 1); - QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy2.at(0).at(0).constData()), QProcess::Crashed); -#endif } void tst_QProcess::waitForFinished() @@ -724,15 +745,14 @@ void tst_QProcess::restartProcessDeadlock() // process in the finished() connected slot causes a deadlock // because of the way QProcessManager uses its locks. QProcess process; - connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished), - this, &tst_QProcess::restartProcess); + connect(&process, &QProcess::finished, this, &tst_QProcess::restartProcess); process.start("testProcessEcho/testProcessEcho"); QCOMPARE(process.write("", 1), qlonglong(1)); QVERIFY(process.waitForFinished(5000)); - QObject::disconnect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished), nullptr, nullptr); + QObject::disconnect(&process, &QProcess::finished, nullptr, nullptr); QCOMPARE(process.write("", 1), qlonglong(1)); QVERIFY(process.waitForFinished(5000)); @@ -857,7 +877,7 @@ void tst_QProcess::emitReadyReadOnlyWhenNewDataArrives() proc.start("testProcessEcho/testProcessEcho"); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); proc.write("A"); @@ -865,7 +885,7 @@ void tst_QProcess::emitReadyReadOnlyWhenNewDataArrives() if (QTestEventLoop::instance().timeout()) QFAIL("Operation timed out"); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QTestEventLoop::instance().enterLoop(1); QVERIFY(QTestEventLoop::instance().timeout()); @@ -931,8 +951,7 @@ public: SoftExitProcess(int n) : waitedForFinished(false), n(n), killing(false) { - connect(this, static_cast<QProcessFinishedSignal2>(&QProcess::finished), - this, &SoftExitProcess::finishedSlot); + connect(this, &QProcess::finished, this, &SoftExitProcess::finishedSlot); switch (n) { case 0: @@ -1055,6 +1074,16 @@ void tst_QProcess::mergedChannels() QVERIFY(process.waitForStarted(5000)); + { + QCOMPARE(process.write("abc"), qlonglong(3)); + while (process.bytesAvailable() < 6) + QVERIFY(process.waitForReadyRead(5000)); + QCOMPARE(process.readAllStandardOutput(), QByteArray("aabbcc")); + QTest::ignoreMessage(QtWarningMsg, + "QProcess::readAllStandardError: Called with MergedChannels"); + QCOMPARE(process.readAllStandardError(), QByteArray()); + } + for (int i = 0; i < 100; ++i) { QCOMPARE(process.write("abc"), qlonglong(3)); while (process.bytesAvailable() < 6) @@ -1100,6 +1129,10 @@ void tst_QProcess::forwardedChannels_data() << true << int(QProcess::SeparateChannels) << int(QProcess::ManagedInputChannel) << QByteArray("out data") << QByteArray("err data"); + QTest::newRow("detached-merged-forwarding") + << true + << int(QProcess::MergedChannels) << int(QProcess::ManagedInputChannel) + << QByteArray("out data" "err data") << QByteArray(); } void tst_QProcess::forwardedChannels() @@ -1117,9 +1150,8 @@ void tst_QProcess::forwardedChannels() QVERIFY(process.waitForStarted(5000)); QCOMPARE(process.write("input"), 5); process.closeWriteChannel(); - QVERIFY(process.waitForFinished(5000)); + QVERIFY(process.waitForFinished(40000)); // testForwarding has a 30s wait QCOMPARE(process.exitStatus(), QProcess::NormalExit); - QCOMPARE(process.exitCode(), 0); const char *err; switch (process.exitCode()) { case 0: err = "ok"; break; @@ -1172,13 +1204,12 @@ public: } protected: - inline void run() + inline void run() override { exitCode = 90210; QProcess process; - connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished), - this, &TestThread::catchExitCode, Qt::DirectConnection); + connect(&process, &QProcess::finished, this, &TestThread::catchExitCode, Qt::DirectConnection); process.start("testProcessEcho/testProcessEcho"); @@ -1209,8 +1240,13 @@ void tst_QProcess::processInAThread() void tst_QProcess::processesInMultipleThreads() { - if (EmulationDetector::isRunningArmOnX86()) - QSKIP("Flakily hangs in QEMU. QTBUG-67760"); + if (QTestPrivate::isRunningArmOnX86()) + QSKIP("Test is too slow to run on emulator"); + +#if defined(Q_OS_QNX) + QSKIP("QNX: Large amount of threads is unstable and do not finish in given time"); +#endif + for (int i = 0; i < 10; ++i) { // run from 1 to 10 threads, but run at least some tests // with more threads than the ideal @@ -1218,18 +1254,16 @@ void tst_QProcess::processesInMultipleThreads() if (i > 7) threadCount = qMax(threadCount, QThread::idealThreadCount() + 2); - QVector<TestThread *> threads(threadCount); + QList<TestThread *> threads(threadCount); + QScopeGuard cleanup([&threads]() { qDeleteAll(threads); }); for (int j = 0; j < threadCount; ++j) threads[j] = new TestThread; for (int j = 0; j < threadCount; ++j) threads[j]->start(); - for (int j = 0; j < threadCount; ++j) { + for (int j = 0; j < threadCount; ++j) QVERIFY(threads[j]->wait(10000)); - } - for (int j = 0; j < threadCount; ++j) { + for (int j = 0; j < threadCount; ++j) QCOMPARE(threads[j]->code(), 0); - } - qDeleteAll(threads); } } @@ -1251,8 +1285,7 @@ void tst_QProcess::waitForReadyReadInAReadyReadSlot() { QProcess process; connect(&process, &QIODevice::readyRead, this, &tst_QProcess::waitForReadyReadInAReadyReadSlotSlot); - connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished), - this, &tst_QProcess::exitLoopSlot); + connect(&process, &QProcess::finished, this, &tst_QProcess::exitLoopSlot); bytesAvailable = 0; process.start("testProcessEcho/testProcessEcho"); @@ -1264,13 +1297,13 @@ void tst_QProcess::waitForReadyReadInAReadyReadSlot() QTestEventLoop::instance().enterLoop(30); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); process.disconnect(); QVERIFY(process.waitForFinished(5000)); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); - QVERIFY(process.bytesAvailable() > bytesAvailable); + QVERIFY(process.bytesAvailable() >= bytesAvailable); } void tst_QProcess::waitForReadyReadInAReadyReadSlotSlot() @@ -1280,6 +1313,8 @@ void tst_QProcess::waitForReadyReadInAReadyReadSlotSlot() bytesAvailable = process->bytesAvailable(); process->write("bar", 4); QVERIFY(process->waitForReadyRead(5000)); + QVERIFY(process->bytesAvailable() > bytesAvailable); + bytesAvailable = process->bytesAvailable(); QTestEventLoop::instance().exitLoop(); } @@ -1298,7 +1333,7 @@ void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot() QTestEventLoop::instance().enterLoop(30); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); process.write("", 1); process.disconnect(); QVERIFY(process.waitForFinished()); @@ -1372,6 +1407,9 @@ void tst_QProcess::spaceArgsTest() QFETCH(QStringList, args); QFETCH(QString, stringArgs); + auto splitString = QProcess::splitCommand(stringArgs); + QCOMPARE(args, splitString); + QStringList programs; programs << QString::fromLatin1("testProcessSpacesArgs/nospace") << QString::fromLatin1("testProcessSpacesArgs/one space") @@ -1398,28 +1436,6 @@ void tst_QProcess::spaceArgsTest() actual.removeFirst(); QCOMPARE(actual, args); - - if (program.contains(QLatin1Char(' '))) - program = QLatin1Char('"') + program + QLatin1Char('"'); - - if (!stringArgs.isEmpty()) - program += QLatin1Char(' ') + stringArgs; - - errorMessage.clear(); - process.start(program); - started = process.waitForStarted(5000); - if (!started) - errorMessage = startFailMessage(program, process); - - QVERIFY2(started, errorMessage.constData()); - QVERIFY(process.waitForFinished(5000)); - - actual = QString::fromLatin1(process.readAll()).split("|"); - QVERIFY(!actual.isEmpty()); - // not interested in the program name, it might be different. - actual.removeFirst(); - - QCOMPARE(actual, args); } } @@ -1470,11 +1486,484 @@ void tst_QProcess::createProcessArgumentsModifier() } #endif // Q_OS_WIN +#ifdef Q_OS_UNIX +static constexpr int sigs[] = { SIGABRT, SIGILL, SIGSEGV }; +struct DisableCrashLogger +{ + // disable core dumps too + tst_QProcessCrash::NoCoreDumps disableCoreDumps {}; + std::array<struct sigaction, std::size(sigs)> oldhandlers; + DisableCrashLogger() + { + struct sigaction def = {}; + def.sa_handler = SIG_DFL; + for (uint i = 0; i < std::size(sigs); ++i) + sigaction(sigs[i], &def, &oldhandlers[i]); + } + ~DisableCrashLogger() + { + // restore them + for (uint i = 0; i < std::size(sigs); ++i) + sigaction(sigs[i], &oldhandlers[i], nullptr); + } +}; + +QT_BEGIN_NAMESPACE +Q_AUTOTEST_EXPORT bool _qprocessUsingVfork() noexcept; +QT_END_NAMESPACE +static constexpr char messageFromChildProcess[] = "Message from the child process"; +static_assert(std::char_traits<char>::length(messageFromChildProcess) <= PIPE_BUF); +static void childProcessModifier(int fd) +{ + QT_WRITE(fd, messageFromChildProcess, strlen(messageFromChildProcess)); + QT_CLOSE(fd); +} + +void tst_QProcess::setChildProcessModifier_data() +{ + QTest::addColumn<bool>("detached"); + QTest::addColumn<bool>("useVfork"); + QTest::newRow("normal") << false << false; + QTest::newRow("detached") << true << false; + +#ifdef QT_BUILD_INTERNAL + if (_qprocessUsingVfork()) { + QTest::newRow("normal-vfork") << false << true; + QTest::newRow("detached-vfork") << true << true; + } +#endif +} + +void tst_QProcess::setChildProcessModifier() +{ + QFETCH(bool, detached); + QFETCH(bool, useVfork); + int pipes[2] = { -1 , -1 }; + QVERIFY(qt_safe_pipe(pipes) == 0); + + QProcess process; + if (useVfork) + process.setUnixProcessParameters(QProcess::UnixProcessFlag::UseVFork); + process.setChildProcessModifier([pipes]() { + ::childProcessModifier(pipes[1]); + }); + process.setProgram("testProcessNormal/testProcessNormal"); + if (detached) { + process.startDetached(); + } else { + process.start("testProcessNormal/testProcessNormal"); + if (process.state() != QProcess::Starting) + QCOMPARE(process.state(), QProcess::Running); + QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString())); + QVERIFY2(process.waitForFinished(5000), qPrintable(process.errorString())); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); + } + + char buf[sizeof messageFromChildProcess] = {}; + qt_safe_close(pipes[1]); + QCOMPARE(qt_safe_read(pipes[0], buf, sizeof(buf)), qint64(sizeof(messageFromChildProcess)) - 1); + QCOMPARE(buf, messageFromChildProcess); + qt_safe_close(pipes[0]); +} + +void tst_QProcess::failChildProcessModifier() +{ + static const char failureMsg[] = + "Some error message from the child process would go here if this were a " + "real application"; + static_assert(sizeof(failureMsg) < _POSIX_PIPE_BUF / 2, + "Implementation detail: the length of the message is limited"); + + QFETCH(bool, detached); + QFETCH(bool, useVfork); + + QProcess process; + if (useVfork) + process.setUnixProcessParameters(QProcess::UnixProcessFlag::UseVFork); + process.setChildProcessModifier([&process]() { + process.failChildProcessModifier(failureMsg, EPERM); + }); + process.setProgram("testProcessNormal/testProcessNormal"); + + if (detached) { + qint64 pid; + QVERIFY(!process.startDetached(&pid)); + QCOMPARE(pid, -1); + } else { + process.start(); + QVERIFY(!process.waitForStarted(5000)); + } + + QString errMsg = process.errorString(); + QVERIFY2(errMsg.startsWith("Child process modifier reported error: "_L1 + failureMsg), + qPrintable(errMsg)); + QVERIFY2(errMsg.endsWith(strerror(EPERM)), qPrintable(errMsg)); +} + +void tst_QProcess::throwInChildProcessModifier() +{ +#ifndef __cpp_exceptions + Q_SKIP("Exceptions disabled."); +#else + static constexpr char What[] = "tst_QProcess::throwInChildProcessModifier()::MyException"; + struct MyException : std::exception { + const char *what() const noexcept override { return What; } + }; + QProcess process; + process.setChildProcessModifier([]() { + throw MyException(); + }); + process.setProgram("testProcessNormal/testProcessNormal"); + + process.start(); + QVERIFY(!process.waitForStarted(5000)); + QCOMPARE(process.state(), QProcess::NotRunning); + QCOMPARE(process.error(), QProcess::FailedToStart); + QVERIFY2(process.errorString().contains("Child process modifier threw an exception"), + qPrintable(process.errorString())); + QVERIFY2(process.errorString().contains(What), + qPrintable(process.errorString())); + + // try again, to ensure QProcess internal state wasn't corrupted + process.start(); + QVERIFY(!process.waitForStarted(5000)); + QCOMPARE(process.state(), QProcess::NotRunning); + QCOMPARE(process.error(), QProcess::FailedToStart); + QVERIFY2(process.errorString().contains("Child process modifier threw an exception"), + qPrintable(process.errorString())); + QVERIFY2(process.errorString().contains(What), + qPrintable(process.errorString())); +#endif +} + +void tst_QProcess::terminateInChildProcessModifier_data() +{ + using F = std::function<void(void)>; + QTest::addColumn<F>("function"); + QTest::addColumn<QProcess::ExitStatus>("exitStatus"); + QTest::addColumn<bool>("stderrIsEmpty"); + + QTest::newRow("_exit") << F([]() { _exit(0); }) << QProcess::NormalExit << true; + QTest::newRow("abort") << F(std::abort) << QProcess::CrashExit << true; + QTest::newRow("sigkill") << F([]() { raise(SIGKILL); }) << QProcess::CrashExit << true; + QTest::newRow("terminate") << F(std::terminate) << QProcess::CrashExit + << (std::get_terminate() == std::abort); + QTest::newRow("crash") << F([]() { tst_QProcessCrash::crash(); }) << QProcess::CrashExit << true; +} + +void tst_QProcess::terminateInChildProcessModifier() +{ + QFETCH(std::function<void(void)>, function); + QFETCH(QProcess::ExitStatus, exitStatus); + QFETCH(bool, stderrIsEmpty); + + // temporarily disable QTest's crash logger + DisableCrashLogger disableCrashLogging; + + // testForwardingHelper prints to both stdout and stderr, so if we fail to + // fail we should be able to tell too + QProcess process; + process.setChildProcessModifier(function); + process.setProgram("testForwardingHelper/testForwardingHelper"); + process.setArguments({ "/dev/null" }); + + // temporarily disable QTest's crash logger while starting the child process + { + DisableCrashLogger d; + process.start(); + } + + QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString())); + QVERIFY2(process.waitForFinished(5000), qPrintable(process.errorString())); + QCOMPARE(process.exitStatus(), exitStatus); + QCOMPARE(process.readAllStandardOutput(), QByteArray()); + + // some environments print extra stuff to stderr when we crash +#ifndef Q_OS_QNX + if (!QTestPrivate::isRunningArmOnX86()) { + QByteArray standardError = process.readAllStandardError(); + QVERIFY2(standardError.isEmpty() == stderrIsEmpty, + "stderr was: " + standardError); + } +#endif +} + +void tst_QProcess::raiseInChildProcessModifier() +{ +#ifdef QT_BUILD_INTERNAL + // This is similar to the above, but knowing that raise() doesn't unblock + // signals, unlike abort(), this implies that + // 1) the raise() in the child modifier will not run our handler + // 2) the write() to stdout after that will run + // 3) QProcess resets the signal handlers to the defaults, then unblocks + // 4) at that point, the signal will be delivered to the child, but our + // handler is no longer active so there'll be no write() to stderr + // + // Note for maintenance: if in the future this test causes the parent + // process to die with SIGUSR1, it means the C library is buggy and is + // using a cached PID in the child process after vfork(). + if (!QT_PREPEND_NAMESPACE(_qprocessUsingVfork())) + QSKIP("QProcess will only block Unix signals when using vfork()"); + + // we use SIGUSR1 because QtTest doesn't log it and because its default + // action is termination, not core dumping + struct SigUsr1Handler { + SigUsr1Handler() + { + struct sigaction sa = {}; + sa.sa_flags = SA_RESETHAND; + sa.sa_handler = [](int) { + static const char msg[] = "SIGUSR1 handler was run"; + write(STDERR_FILENO, msg, strlen(msg)); + raise(SIGUSR1); // re-raise + }; + sigaction(SIGUSR1, &sa, nullptr); + } + ~SigUsr1Handler() { restore(); } + static void restore() { signal(SIGUSR1, SIG_DFL); } + } sigUsr1Handler; + + QProcess process; + + // QProcess will block signals with UseVFork + process.setUnixProcessParameters(QProcess::UnixProcessFlag::UseVFork | + QProcess::UnixProcessFlag::ResetSignalHandlers); + process.setChildProcessModifier([]() { + raise(SIGUSR1); + ::childProcessModifier(STDOUT_FILENO); + }); + + // testForwardingHelper prints to both stdout and stderr, so if we fail to + // fail we should be able to tell too + process.setProgram("testForwardingHelper/testForwardingHelper"); + process.setArguments({ "/dev/null" }); + + process.start(); + QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString())); + QVERIFY2(process.waitForFinished(5000), qPrintable(process.errorString())); + QCOMPARE(process.error(), QProcess::Crashed); + + // ensure the write() from the child modifier DID get run + QCOMPARE(process.readAllStandardOutput(), messageFromChildProcess); + + // some environments print extra stuff to stderr when we crash + if (!QTestPrivate::isRunningArmOnX86()) { + // and write() from the SIGUSR1 handler did not + QCOMPARE(process.readAllStandardError(), QByteArray()); + } +#else + QSKIP("Requires QT_BUILD_INTERNAL symbols"); +#endif +} + +void tst_QProcess::unixProcessParameters_data() +{ + QTest::addColumn<QProcess::UnixProcessParameters>("params"); + QTest::addColumn<QString>("cmd"); + QTest::newRow("defaults") << QProcess::UnixProcessParameters{} << QString(); + + auto addRow = [](const char *cmd, QProcess::UnixProcessFlags flags) { + QProcess::UnixProcessParameters params = {}; + params.flags = flags; + QTest::addRow("%s", cmd) << params << cmd; + }; + using P = QProcess::UnixProcessFlag; + addRow("reset-sighand", P::ResetSignalHandlers); + addRow("ignore-sigpipe", P::IgnoreSigPipe); + addRow("file-descriptors", P::CloseFileDescriptors); + addRow("setsid", P::CreateNewSession); + addRow("reset-ids", P::ResetIds); + + // On FreeBSD, we need to be session leader to disconnect from the CTTY + addRow("noctty", P::DisconnectControllingTerminal | P::CreateNewSession); +} + +void tst_QProcess::unixProcessParameters() +{ + QFETCH(QProcess::UnixProcessParameters, params); + QFETCH(QString, cmd); + + // set up a few things + struct Scope { + int devnull; + struct sigaction old_sigusr1, old_sigpipe; + Scope() + { + int fd = open("/dev/null", O_RDONLY); + devnull = fcntl(fd, F_DUPFD, 100); + close(fd); + + // we ignore SIGUSR1 and reset SIGPIPE to Terminate + struct sigaction act = {}; + sigemptyset(&act.sa_mask); + act.sa_handler = SIG_IGN; + sigaction(SIGUSR1, &act, &old_sigusr1); + act.sa_handler = SIG_DFL; + sigaction(SIGPIPE, &act, &old_sigpipe); + + // and we block SIGUSR2 + sigset_t *set = &act.sa_mask; // reuse this sigset_t + sigaddset(set, SIGUSR2); + sigprocmask(SIG_BLOCK, set, nullptr); + } + ~Scope() + { + if (devnull != -1) + dismiss(); + } + void dismiss() + { + close(devnull); + sigaction(SIGUSR1, &old_sigusr1, nullptr); + sigaction(SIGPIPE, &old_sigpipe, nullptr); + devnull = -1; + + sigset_t *set = &old_sigusr1.sa_mask; // reuse this sigset_t + sigaddset(set, SIGUSR2); + sigprocmask(SIG_BLOCK, set, nullptr); + } + } scope; + + if (params.flags & QProcess::UnixProcessFlag::ResetIds) { + if (getuid() == geteuid() && getgid() == getegid()) + qInfo("Process has identical real and effective IDs; this test will do nothing"); + } + + if (params.flags & QProcess::UnixProcessFlag::DisconnectControllingTerminal) { + if (int fd = open("/dev/tty", O_RDONLY); fd < 0) { + qInfo("Process has no controlling terminal; this test will do nothing"); + close(fd); + } + } + + QProcess process; + process.setUnixProcessParameters(params); + process.setStandardInputFile(QProcess::nullDevice()); // so we can't mess with SIGPIPE + process.setProgram("testUnixProcessParameters/testUnixProcessParameters"); + process.setArguments({ cmd, QString::number(scope.devnull) }); + process.start(); + QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString())); + QVERIFY(process.waitForFinished(5000)); + + const QString stdErr = process.readAllStandardError(); + QCOMPARE(stdErr, QString()); + QCOMPARE(process.readAll(), QString()); + QCOMPARE(process.exitCode(), 0); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); +} + +void tst_QProcess::impossibleUnixProcessParameters_data() +{ + using P = QProcess::UnixProcessParameters; + QTest::addColumn<P>("params"); + QTest::newRow("setsid") << P{ QProcess::UnixProcessFlag::CreateNewSession }; +} + +void tst_QProcess::impossibleUnixProcessParameters() +{ + QFETCH(QProcess::UnixProcessParameters, params); + + QProcess process; + if (params.flags & QProcess::UnixProcessFlag::CreateNewSession) { + process.setChildProcessModifier([]() { + // double setsid() should cause the second to fail + setsid(); + }); + } + process.setUnixProcessParameters(params); + process.start("testProcessNormal/testProcessNormal"); + + QVERIFY(!process.waitForStarted(5000)); + qDebug() << process.errorString(); +} + +void tst_QProcess::unixProcessParametersAndChildModifier() +{ + static constexpr char message[] = "Message from the handler function\n"; + static_assert(std::char_traits<char>::length(message) <= PIPE_BUF); + QProcess process; + QAtomicInt vforkControl; + int pipes[2]; + + pid_t oldpgid = getpgrp(); + + QVERIFY2(pipe(pipes) == 0, qPrintable(qt_error_string())); + auto pipeGuard0 = qScopeGuard([=] { close(pipes[0]); }); + { + auto pipeGuard1 = qScopeGuard([=] { close(pipes[1]); }); + + // verify that our modifier runs before the parameters are applied + process.setChildProcessModifier([=, &vforkControl] { + const char *pgidmsg = "PGID mismatch. "; + if (getpgrp() != oldpgid) + write(pipes[1], pgidmsg, strlen(pgidmsg)); + write(pipes[1], message, strlen(message)); + vforkControl.storeRelaxed(1); + }); + auto flags = QProcess::UnixProcessFlag::CloseFileDescriptors | + QProcess::UnixProcessFlag::CreateNewSession | + QProcess::UnixProcessFlag::UseVFork; + process.setUnixProcessParameters({ flags }); + process.setProgram("testUnixProcessParameters/testUnixProcessParameters"); + process.setArguments({ "file-descriptors", QString::number(pipes[1]) }); + process.start(); + QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString())); + } // closes the writing end of the pipe + + QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.readAllStandardError(), QString()); + QCOMPARE(process.readAll(), QString()); + + char buf[2 * sizeof(message)]; + int r = read(pipes[0], buf, sizeof(buf)); + QVERIFY2(r >= 0, qPrintable(qt_error_string())); + QCOMPARE(QByteArrayView(buf, r), message); + + if (haveWorkingVFork) + QVERIFY2(vforkControl.loadRelaxed(), "QProcess doesn't appear to have used vfork()"); +} + +void tst_QProcess::unixProcessParametersOtherFileDescriptors() +{ + constexpr int TargetFileDescriptor = 3; + int fd1 = open("/dev/null", O_RDONLY); + int devnull = fcntl(fd1, F_DUPFD, 100); // instead of F_DUPFD_CLOEXEC + close(fd1); + + auto closeFds = qScopeGuard([&] { + close(devnull); + }); + + QProcess process; + QProcess::UnixProcessParameters params; + params.flags = QProcess::UnixProcessFlag::CloseFileDescriptors + | QProcess::UnixProcessFlag::UseVFork; + params.lowestFileDescriptorToClose = 4; + process.setUnixProcessParameters(params); + process.setChildProcessModifier([devnull, &process]() { + if (dup2(devnull, TargetFileDescriptor) != TargetFileDescriptor) + process.failChildProcessModifier("dup2", errno); + }); + process.setProgram("testUnixProcessParameters/testUnixProcessParameters"); + process.setArguments({ "file-descriptors2", QString::number(TargetFileDescriptor), + QString::number(devnull) }); + process.start(); + + QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString())); + QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.readAllStandardError(), QString()); + QCOMPARE(process.readAll(), QString()); + QCOMPARE(process.exitCode(), 0); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); +} +#endif + void tst_QProcess::exitCodeTest() { for (int i = 0; i < 255; ++i) { QProcess process; - process.start("testExitCodes/testExitCodes " + QString::number(i)); + process.start("testExitCodes/testExitCodes", {QString::number(i)}); QVERIFY(process.waitForFinished(5000)); QCOMPARE(process.exitCode(), i); QCOMPARE(process.error(), QProcess::UnknownError); @@ -1490,25 +1979,16 @@ void tst_QProcess::failToStart() QProcess process; QSignalSpy stateSpy(&process, &QProcess::stateChanged); QSignalSpy errorSpy(&process, &QProcess::errorOccurred); - QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished)); + QSignalSpy finishedSpy(&process, &QProcess::finished); QVERIFY(stateSpy.isValid()); QVERIFY(errorSpy.isValid()); QVERIFY(finishedSpy.isValid()); -#if QT_DEPRECATED_SINCE(5, 6) - QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error)); - QVERIFY(errorSpy2.isValid()); -#endif -#if QT_DEPRECATED_SINCE(5, 13) - QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished)); - QVERIFY(finishedSpy2.isValid()); -#endif - // OS X and HP-UX have a really low default process limit (~100), so spawning // to many processes here will cause test failures later on. #if defined Q_OS_HPUX const int attempts = 15; -#elif defined Q_OS_MAC +#elif defined Q_OS_DARWIN const int attempts = 15; #else const int attempts = 50; @@ -1516,10 +1996,7 @@ void tst_QProcess::failToStart() for (int j = 0; j < 8; ++j) { for (int i = 0; i < attempts; ++i) { - QCOMPARE(errorSpy.count(), j * attempts + i); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(errorSpy2.count(), j * attempts + i); -#endif + QCOMPARE(errorSpy.size(), j * attempts + i); process.start("/blurp"); switch (j) { @@ -1543,18 +2020,12 @@ void tst_QProcess::failToStart() } QCOMPARE(process.error(), QProcess::FailedToStart); - QCOMPARE(errorSpy.count(), j * attempts + i + 1); - QCOMPARE(finishedSpy.count(), 0); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(errorSpy2.count(), j * attempts + i + 1); -#endif -#if QT_DEPRECATED_SINCE(5, 13) - QCOMPARE(finishedSpy2.count(), 0); -#endif + QCOMPARE(errorSpy.size(), j * attempts + i + 1); + QCOMPARE(finishedSpy.size(), 0); int it = j * attempts + i + 1; - QCOMPARE(stateSpy.count(), it * 2); + QCOMPARE(stateSpy.size(), it * 2); QCOMPARE(qvariant_cast<QProcess::ProcessState>(stateSpy.at(it * 2 - 2).at(0)), QProcess::Starting); QCOMPARE(qvariant_cast<QProcess::ProcessState>(stateSpy.at(it * 2 - 1).at(0)), QProcess::NotRunning); } @@ -1569,33 +2040,17 @@ void tst_QProcess::failToStartWithWait() QProcess process; QEventLoop loop; QSignalSpy errorSpy(&process, &QProcess::errorOccurred); - QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished)); + QSignalSpy finishedSpy(&process, &QProcess::finished); QVERIFY(errorSpy.isValid()); QVERIFY(finishedSpy.isValid()); -#if QT_DEPRECATED_SINCE(5, 6) - QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error)); - QVERIFY(errorSpy2.isValid()); -#endif -#if QT_DEPRECATED_SINCE(5, 13) - QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished)); - QVERIFY(finishedSpy2.isValid()); -#endif - for (int i = 0; i < 50; ++i) { process.start("/blurp", QStringList() << "-v" << "-debug"); process.waitForStarted(); QCOMPARE(process.error(), QProcess::FailedToStart); - QCOMPARE(errorSpy.count(), i + 1); - QCOMPARE(finishedSpy.count(), 0); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(errorSpy2.count(), i + 1); -#endif -#if QT_DEPRECATED_SINCE(5, 13) - QCOMPARE(finishedSpy2.count(), 0); -#endif - + QCOMPARE(errorSpy.size(), i + 1); + QCOMPARE(finishedSpy.size(), 0); } } @@ -1607,19 +2062,10 @@ void tst_QProcess::failToStartWithEventLoop() QProcess process; QEventLoop loop; QSignalSpy errorSpy(&process, &QProcess::errorOccurred); - QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished)); + QSignalSpy finishedSpy(&process, &QProcess::finished); QVERIFY(errorSpy.isValid()); QVERIFY(finishedSpy.isValid()); -#if QT_DEPRECATED_SINCE(5, 6) - QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error)); - QVERIFY(errorSpy2.isValid()); -#endif -#if QT_DEPRECATED_SINCE(5, 13) - QSignalSpy finishedSpy2(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished)); - QVERIFY(finishedSpy2.isValid()); -#endif - // The error signal may be emitted before start() returns connect(&process, &QProcess::errorOccurred, &loop, &QEventLoop::quit, Qt::QueuedConnection); @@ -1630,14 +2076,8 @@ void tst_QProcess::failToStartWithEventLoop() loop.exec(); QCOMPARE(process.error(), QProcess::FailedToStart); - QCOMPARE(errorSpy.count(), i + 1); - QCOMPARE(finishedSpy.count(), 0); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(errorSpy2.count(), i + 1); -#endif -#if QT_DEPRECATED_SINCE(5, 13) - QCOMPARE(finishedSpy2.count(), 0); -#endif + QCOMPARE(errorSpy.size(), i + 1); + QCOMPARE(finishedSpy.size(), 0); } } @@ -1645,8 +2085,7 @@ void tst_QProcess::failToStartEmptyArgs_data() { QTest::addColumn<int>("startOverload"); QTest::newRow("start(QString, QStringList, OpenMode)") << 0; - QTest::newRow("start(QString, OpenMode)") << 1; - QTest::newRow("start(OpenMode)") << 2; + QTest::newRow("start(OpenMode)") << 1; } void tst_QProcess::failToStartEmptyArgs() @@ -1657,19 +2096,12 @@ void tst_QProcess::failToStartEmptyArgs() QProcess process; QSignalSpy errorSpy(&process, static_cast<QProcessErrorSignal>(&QProcess::errorOccurred)); QVERIFY(errorSpy.isValid()); -#if QT_DEPRECATED_SINCE(5, 6) - QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error)); - QVERIFY(errorSpy2.isValid()); -#endif switch (startOverload) { case 0: process.start(QString(), QStringList(), QIODevice::ReadWrite); break; case 1: - process.start(QString(), QIODevice::ReadWrite); - break; - case 2: process.start(QIODevice::ReadWrite); break; default: @@ -1677,10 +2109,7 @@ void tst_QProcess::failToStartEmptyArgs() }; QVERIFY(!process.waitForStarted()); - QCOMPARE(errorSpy.count(), 1); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(errorSpy2.count(), 1); -#endif + QCOMPARE(errorSpy.size(), 1); QCOMPARE(process.error(), QProcess::FailedToStart); } @@ -1737,9 +2166,9 @@ void tst_QProcess::setEnvironment() QStringList environment = QProcess::systemEnvironment(); if (value.isNull()) { int pos; - QRegExp rx(name + "=.*"); + QRegularExpression rx(name + "=.*"); #ifdef Q_OS_WIN - rx.setCaseSensitivity(Qt::CaseInsensitive); + rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption); #endif while ((pos = environment.indexOf(rx)) != -1) environment.removeAt(pos); @@ -1862,7 +2291,7 @@ void tst_QProcess::systemEnvironment() QVERIFY(!QProcessEnvironment::systemEnvironment().isEmpty()); QVERIFY(QProcessEnvironment::systemEnvironment().contains("PATH")); - QVERIFY(!QProcess::systemEnvironment().filter(QRegExp("^PATH=", Qt::CaseInsensitive)).isEmpty()); + QVERIFY(!QProcess::systemEnvironment().filter(QRegularExpression("^PATH=", QRegularExpression::CaseInsensitiveOption)).isEmpty()); } void tst_QProcess::spaceInName() @@ -1912,32 +2341,16 @@ void tst_QProcess::waitForReadyReadForNonexistantProcess() QProcess process; QSignalSpy errorSpy(&process, &QProcess::errorOccurred); - QSignalSpy finishedSpy(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished)); + QSignalSpy finishedSpy(&process, &QProcess::finished); QVERIFY(errorSpy.isValid()); QVERIFY(finishedSpy.isValid()); -#if QT_DEPRECATED_SINCE(5, 6) - QSignalSpy errorSpy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error)); - QVERIFY(errorSpy2.isValid()); -#endif -#if QT_DEPRECATED_SINCE(5, 13) - QSignalSpy finishedSpy1(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished)); - QVERIFY(finishedSpy1.isValid()); -#endif - QVERIFY(!process.waitForReadyRead()); // used to crash process.start("doesntexist"); QVERIFY(!process.waitForReadyRead()); - QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorSpy.size(), 1); QCOMPARE(errorSpy.at(0).at(0).toInt(), 0); - QCOMPARE(finishedSpy.count(), 0); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(errorSpy2.count(), 1); - QCOMPARE(errorSpy2.at(0).at(0).toInt(), 0); -#endif -#if QT_DEPRECATED_SINCE(5, 13) - QCOMPARE(finishedSpy1.count(), 0); -#endif + QCOMPARE(finishedSpy.size(), 0); } void tst_QProcess::setStandardInputFile() @@ -1946,12 +2359,21 @@ void tst_QProcess::setStandardInputFile() QProcess process; QFile file(m_temporaryDir.path() + QLatin1String("/data-sif")); + QSignalSpy stateSpy(&process, &QProcess::stateChanged); + QSignalSpy errorOccurredSpy(&process, &QProcess::errorOccurred); + QVERIFY(file.open(QIODevice::WriteOnly)); file.write(data, sizeof data); file.close(); process.setStandardInputFile(file.fileName()); process.start("testProcessEcho/testProcessEcho"); + QVERIFY(process.waitForStarted()); + QCOMPARE(errorOccurredSpy.size(), 0); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy[0][0].value<QProcess::ProcessState>(), QProcess::Starting); + QCOMPARE(stateSpy[1][0].value<QProcess::ProcessState>(), QProcess::Running); + stateSpy.clear(); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); @@ -1968,31 +2390,50 @@ void tst_QProcess::setStandardInputFile() QCOMPARE(all.size(), 0); } +void tst_QProcess::setStandardInputFileFailure() +{ + QProcess process; + process.setStandardInputFile(nonExistentFileName); + + QSignalSpy stateSpy(&process, &QProcess::stateChanged); + QSignalSpy errorOccurredSpy(&process, &QProcess::errorOccurred); + + process.start("testProcessEcho/testProcessEcho"); + QVERIFY(!process.waitForStarted()); + + QCOMPARE(errorOccurredSpy.size(), 1); + QCOMPARE(errorOccurredSpy[0][0].value<QProcess::ProcessError>(), QProcess::FailedToStart); + + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy[0][0].value<QProcess::ProcessState>(), QProcess::Starting); + QCOMPARE(stateSpy[1][0].value<QProcess::ProcessState>(), QProcess::NotRunning); +} + void tst_QProcess::setStandardOutputFile_data() { - QTest::addColumn<int>("channelToTest"); - QTest::addColumn<int>("_channelMode"); + QTest::addColumn<QProcess::ProcessChannel>("channelToTest"); + QTest::addColumn<QProcess::ProcessChannelMode>("channelMode"); QTest::addColumn<bool>("append"); - QTest::newRow("stdout-truncate") << int(QProcess::StandardOutput) - << int(QProcess::SeparateChannels) + QTest::newRow("stdout-truncate") << QProcess::StandardOutput + << QProcess::SeparateChannels << false; - QTest::newRow("stdout-append") << int(QProcess::StandardOutput) - << int(QProcess::SeparateChannels) + QTest::newRow("stdout-append") << QProcess::StandardOutput + << QProcess::SeparateChannels << true; - QTest::newRow("stderr-truncate") << int(QProcess::StandardError) - << int(QProcess::SeparateChannels) + QTest::newRow("stderr-truncate") << QProcess::StandardError + << QProcess::SeparateChannels << false; - QTest::newRow("stderr-append") << int(QProcess::StandardError) - << int(QProcess::SeparateChannels) + QTest::newRow("stderr-append") << QProcess::StandardError + << QProcess::SeparateChannels << true; - QTest::newRow("merged-truncate") << int(QProcess::StandardOutput) - << int(QProcess::MergedChannels) + QTest::newRow("merged-truncate") << QProcess::StandardOutput + << QProcess::MergedChannels << false; - QTest::newRow("merged-append") << int(QProcess::StandardOutput) - << int(QProcess::MergedChannels) + QTest::newRow("merged-append") << QProcess::StandardOutput + << QProcess::MergedChannels << true; } @@ -2001,11 +2442,10 @@ void tst_QProcess::setStandardOutputFile() static const char data[] = "Original data. "; static const char testdata[] = "Test data."; - QFETCH(int, channelToTest); - QFETCH(int, _channelMode); + QFETCH(QProcess::ProcessChannel, channelToTest); + QFETCH(QProcess::ProcessChannelMode, channelMode); QFETCH(bool, append); - QProcess::ProcessChannelMode channelMode = QProcess::ProcessChannelMode(_channelMode); QIODevice::OpenMode mode = append ? QIODevice::Append : QIODevice::Truncate; // create the destination file with data @@ -2022,7 +2462,17 @@ void tst_QProcess::setStandardOutputFile() else process.setStandardErrorFile(file.fileName(), mode); + QSignalSpy stateSpy(&process, &QProcess::stateChanged); + QSignalSpy errorOccurredSpy(&process, &QProcess::errorOccurred); + process.start("testProcessEcho2/testProcessEcho2"); + QVERIFY(process.waitForStarted()); + QCOMPARE(errorOccurredSpy.size(), 0); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy[0][0].value<QProcess::ProcessState>(), QProcess::Starting); + QCOMPARE(stateSpy[1][0].value<QProcess::ProcessState>(), QProcess::Running); + stateSpy.clear(); + process.write(testdata, sizeof testdata); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); @@ -2047,6 +2497,34 @@ void tst_QProcess::setStandardOutputFile() QCOMPARE(all.size(), expectedsize); } +void tst_QProcess::setStandardOutputFileFailure() +{ + QFETCH(QProcess::ProcessChannel, channelToTest); + QFETCH(QProcess::ProcessChannelMode, channelMode); + QFETCH(bool, append); + + QIODevice::OpenMode mode = append ? QIODevice::Append : QIODevice::Truncate; + + // run the process + QProcess process; + process.setProcessChannelMode(channelMode); + if (channelToTest == QProcess::StandardOutput) + process.setStandardOutputFile(nonExistentFileName, mode); + else + process.setStandardErrorFile(nonExistentFileName, mode); + + QSignalSpy stateSpy(&process, &QProcess::stateChanged); + QSignalSpy errorOccurredSpy(&process, &QProcess::errorOccurred); + + process.start("testProcessEcho2/testProcessEcho2"); + QVERIFY(!process.waitForStarted()); + QCOMPARE(errorOccurredSpy.size(), 1); + QCOMPARE(errorOccurredSpy[0][0].value<QProcess::ProcessError>(), QProcess::FailedToStart); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy[0][0].value<QProcess::ProcessState>(), QProcess::Starting); + QCOMPARE(stateSpy[1][0].value<QProcess::ProcessState>(), QProcess::NotRunning); +} + void tst_QProcess::setStandardOutputFileNullDevice() { static const char testdata[] = "Test data."; @@ -2098,14 +2576,18 @@ void tst_QProcess::setStandardOutputProcess_data() void tst_QProcess::setStandardOutputProcess() { QProcess source; + QProcess intermediate; QProcess sink; QFETCH(bool, merged); QFETCH(bool, waitForBytesWritten); source.setProcessChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels); - source.setStandardOutputProcess(&sink); + source.setStandardOutputProcess(&intermediate); + intermediate.setStandardOutputProcess(&sink); source.start("testProcessEcho2/testProcessEcho2"); + intermediate.setProgram("testProcessEcho/testProcessEcho"); + QVERIFY(intermediate.startDetached()); sink.start("testProcessEcho2/testProcessEcho2"); QByteArray data("Hello, World"); @@ -2147,7 +2629,7 @@ void tst_QProcess::fileWriterProcess() QVERIFY(QFile::remove(fileName)); QProcess process; process.setWorkingDirectory(m_temporaryDir.path()); - process.start(binary, QIODevice::ReadWrite | QIODevice::Text); + process.start(binary, {}, QIODevice::ReadWrite | QIODevice::Text); process.write(stdinStr); process.closeWriteChannel(); while (process.bytesToWrite()) { @@ -2318,18 +2800,48 @@ void tst_QProcess::setWorkingDirectory() void tst_QProcess::setNonExistentWorkingDirectory() { QProcess process; - process.setWorkingDirectory("this/directory/should/not/exist/for/sure"); + process.setWorkingDirectory(nonExistentFileName); + + QSignalSpy stateSpy(&process, &QProcess::stateChanged); + QSignalSpy errorOccurredSpy(&process, &QProcess::errorOccurred); // use absolute path because on Windows, the executable is relative to the parent's CWD // while on Unix with fork it's relative to the child's (with posix_spawn, it could be either). process.start(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath()); + QVERIFY(!process.waitForFinished()); - QCOMPARE(int(process.error()), int(QProcess::FailedToStart)); + QCOMPARE(errorOccurredSpy.size(), 1); + QCOMPARE(process.error(), QProcess::FailedToStart); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy[0][0].value<QProcess::ProcessState>(), QProcess::Starting); + QCOMPARE(stateSpy[1][0].value<QProcess::ProcessState>(), QProcess::NotRunning); + +#ifdef Q_OS_UNIX + QVERIFY2(process.errorString().startsWith("chdir:"), process.errorString().toLocal8Bit()); +#endif +} + +void tst_QProcess::detachedSetNonExistentWorkingDirectory() +{ + QProcess process; + process.setWorkingDirectory(nonExistentFileName); + + QSignalSpy errorOccurredSpy(&process, &QProcess::errorOccurred); + + // use absolute path because on Windows, the executable is relative to the parent's CWD + // while on Unix with fork it's relative to the child's (with posix_spawn, it could be either). + process.setProgram(QFileInfo("testSetWorkingDirectory/testSetWorkingDirectory").absoluteFilePath()); + + qint64 pid = -1; + QVERIFY(!process.startDetached(&pid)); + QCOMPARE(pid, -1); + QCOMPARE(process.error(), QProcess::FailedToStart); + QVERIFY(process.errorString() != "Unknown error"); + + QCOMPARE(errorOccurredSpy.size(), 1); + QCOMPARE(process.error(), QProcess::FailedToStart); #ifdef Q_OS_UNIX -# ifdef QPROCESS_USE_SPAWN - QEXPECT_FAIL("", "QProcess cannot detect failure to start when using posix_spawn()", Continue); -# endif QVERIFY2(process.errorString().startsWith("chdir:"), process.errorString().toLocal8Bit()); #endif } @@ -2358,7 +2870,6 @@ void tst_QProcess::invalidProgramString_data() QTest::addColumn<QString>("programString"); QTest::newRow("null string") << QString(); QTest::newRow("empty string") << QString(""); - QTest::newRow("only blank string") << QString(" "); } void tst_QProcess::invalidProgramString() @@ -2369,17 +2880,10 @@ void tst_QProcess::invalidProgramString() qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); QSignalSpy spy(&process, &QProcess::errorOccurred); QVERIFY(spy.isValid()); -#if QT_DEPRECATED_SINCE(5, 6) - QSignalSpy spy2(&process, static_cast<QProcessErrorSignal>(&QProcess::error)); - QVERIFY(spy2.isValid()); -#endif process.start(programString); QCOMPARE(process.error(), QProcess::FailedToStart); - QCOMPARE(spy.count(), 1); -#if QT_DEPRECATED_SINCE(5, 6) - QCOMPARE(spy2.count(), 1); -#endif + QCOMPARE(spy.size(), 1); QVERIFY(!QProcess::startDetached(programString)); } @@ -2390,7 +2894,7 @@ void tst_QProcess::onlyOneStartedSignal() QProcess process; QSignalSpy spyStarted(&process, &QProcess::started); - QSignalSpy spyFinished(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished)); + QSignalSpy spyFinished(&process, &QProcess::finished); QVERIFY(spyStarted.isValid()); QVERIFY(spyFinished.isValid()); @@ -2398,8 +2902,8 @@ void tst_QProcess::onlyOneStartedSignal() process.start("testProcessNormal/testProcessNormal"); QVERIFY(process.waitForStarted(5000)); QVERIFY(process.waitForFinished(5000)); - QCOMPARE(spyStarted.count(), 1); - QCOMPARE(spyFinished.count(), 1); + QCOMPARE(spyStarted.size(), 1); + QCOMPARE(spyFinished.size(), 1); spyStarted.clear(); spyFinished.clear(); @@ -2408,8 +2912,8 @@ void tst_QProcess::onlyOneStartedSignal() QVERIFY(process.waitForFinished(5000)); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); - QCOMPARE(spyStarted.count(), 1); - QCOMPARE(spyFinished.count(), 1); + QCOMPARE(spyStarted.size(), 1); + QCOMPARE(spyFinished.size(), 1); } class BlockOnReadStdOut : public QObject @@ -2424,7 +2928,7 @@ public: public slots: void block() { - QThread::sleep(1); + QThread::sleep(std::chrono::seconds{1}); } }; @@ -2433,13 +2937,12 @@ void tst_QProcess::finishProcessBeforeReadingDone() QProcess process; BlockOnReadStdOut blocker(&process); QEventLoop loop; - connect(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished), - &loop, &QEventLoop::quit); + connect(&process, &QProcess::finished, &loop, &QEventLoop::quit); process.start("testProcessOutput/testProcessOutput"); QVERIFY(process.waitForStarted()); loop.exec(); QStringList lines = QString::fromLocal8Bit(process.readAllStandardOutput()).split( - QRegExp(QStringLiteral("[\r\n]")), QString::SkipEmptyParts); + QRegularExpression(QStringLiteral("[\r\n]")), Qt::SkipEmptyParts); QVERIFY(!lines.isEmpty()); QCOMPARE(lines.last(), QStringLiteral("10239 -this is a number")); QCOMPARE(process.exitStatus(), QProcess::NormalExit); @@ -2477,23 +2980,23 @@ void tst_QProcess::startStopStartStop() //----------------------------------------------------------------------------- void tst_QProcess::startStopStartStopBuffers_data() { - QTest::addColumn<int>("channelMode1"); - QTest::addColumn<int>("channelMode2"); + QTest::addColumn<QProcess::ProcessChannelMode>("channelMode1"); + QTest::addColumn<QProcess::ProcessChannelMode>("channelMode2"); - QTest::newRow("separate-separate") << int(QProcess::SeparateChannels) << int(QProcess::SeparateChannels); - QTest::newRow("separate-merged") << int(QProcess::SeparateChannels) << int(QProcess::MergedChannels); - QTest::newRow("merged-separate") << int(QProcess::MergedChannels) << int(QProcess::SeparateChannels); - QTest::newRow("merged-merged") << int(QProcess::MergedChannels) << int(QProcess::MergedChannels); - QTest::newRow("merged-forwarded") << int(QProcess::MergedChannels) << int(QProcess::ForwardedChannels); + QTest::newRow("separate-separate") << QProcess::SeparateChannels << QProcess::SeparateChannels; + QTest::newRow("separate-merged") << QProcess::SeparateChannels << QProcess::MergedChannels; + QTest::newRow("merged-separate") << QProcess::MergedChannels << QProcess::SeparateChannels; + QTest::newRow("merged-merged") << QProcess::MergedChannels << QProcess::MergedChannels; + QTest::newRow("merged-forwarded") << QProcess::MergedChannels << QProcess::ForwardedChannels; } void tst_QProcess::startStopStartStopBuffers() { - QFETCH(int, channelMode1); - QFETCH(int, channelMode2); + QFETCH(QProcess::ProcessChannelMode, channelMode1); + QFETCH(QProcess::ProcessChannelMode, channelMode2); QProcess process; - process.setProcessChannelMode(QProcess::ProcessChannelMode(channelMode1)); + process.setProcessChannelMode(channelMode1); process.start("testProcessHang/testProcessHang"); QVERIFY2(process.waitForReadyRead(), process.errorString().toLocal8Bit()); if (channelMode1 == QProcess::SeparateChannels || channelMode1 == QProcess::ForwardedOutputChannel) { @@ -2504,14 +3007,18 @@ void tst_QProcess::startStopStartStopBuffers() } // We want to test that the write buffer still has bytes after the child - // exiting. We do that by writing to a child process that never reads. We - // just have to write more data than a pipe can hold, so that even if - // QProcess finds the pipe writable (during waitForFinished() or in the - // QWindowsPipeWriter thread), some data will remain. The worst case I know - // of is Linux, which defaults to 64 kB of buffer. + // exits. We can do that by writing data until the OS stops consuming data, + // indicating that the pipe buffers are full. The initial value of 128 kB + // should make this loop typicall run only once; the worst case I know of + // is Linux, which defaults to 64 kB of buffer. - process.write(QByteArray(128 * 1024, 'a')); - QVERIFY(process.bytesToWrite() > 0); + QByteArray chunk(128 * 1024, 'a'); + do { + process.write(chunk); + QVERIFY(process.bytesToWrite() > 0); + process.waitForBytesWritten(1); + } while (process.bytesToWrite() == 0); + chunk = {}; process.kill(); QVERIFY(process.waitForFinished()); @@ -2519,7 +3026,8 @@ void tst_QProcess::startStopStartStopBuffers() #ifndef Q_OS_WIN // confirm that our buffers are still full // Note: this doesn't work on Windows because our buffers are drained into - // QWindowsPipeWriter before being sent to the child process. + // QWindowsPipeWriter before being sent to the child process and are lost + // in waitForFinished() -> processFinished() -> cleanup(). QVERIFY(process.bytesToWrite() > 0); QVERIFY(process.bytesAvailable() > 0); // channelMode1 is not ForwardedChannels if (channelMode1 == QProcess::SeparateChannels || channelMode1 == QProcess::ForwardedOutputChannel) { @@ -2529,8 +3037,8 @@ void tst_QProcess::startStopStartStopBuffers() } #endif - process.setProcessChannelMode(QProcess::ProcessChannelMode(channelMode2)); - process.start("testProcessEcho2/testProcessEcho2", QIODevice::ReadWrite | QIODevice::Text); + process.setProcessChannelMode(channelMode2); + process.start("testProcessEcho2/testProcessEcho2", {}, QIODevice::ReadWrite | QIODevice::Text); // the buffers should now be empty QCOMPARE(process.bytesToWrite(), qint64(0)); @@ -2579,106 +3087,94 @@ void tst_QProcess::processEventsInAReadyReadSlot() QVERIFY(process.waitForFinished()); } -#if QT_DEPRECATED_SINCE(5, 13) +enum class ChdirMode { + None = 0, + InParent, + InChild +}; +Q_DECLARE_METATYPE(ChdirMode) -void tst_QProcess::crashTest2_deprecated() +void tst_QProcess::startFromCurrentWorkingDir_data() { - QProcess process; - process.start("testProcessCrash/testProcessCrash"); - QVERIFY(process.waitForStarted(5000)); - - qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); - qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus"); - - QSignalSpy spy(&process, static_cast<QProcessErrorSignal>(&QProcess::errorOccurred)); - QSignalSpy spy2(&process, static_cast<QProcessFinishedSignal2>(&QProcess::finished)); + qRegisterMetaType<ChdirMode>(); + QTest::addColumn<QString>("programPrefix"); + QTest::addColumn<ChdirMode>("chdirMode"); + QTest::addColumn<bool>("success"); - QVERIFY(spy.isValid()); - QVERIFY(spy2.isValid()); + constexpr bool IsWindows = true +#ifdef Q_OS_UNIX + && false +#endif + ; - QObject::connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished), - this, &tst_QProcess::exitLoopSlot); + // baseline: trying to execute the directory, this can't possibly succeed! + QTest::newRow("plain-same-cwd") << QString() << ChdirMode::None << false; - QTestEventLoop::instance().enterLoop(30); - if (QTestEventLoop::instance().timeout()) - QFAIL("Failed to detect crash : operation timed out"); + // cross-platform behavior: neither OS searches the setWorkingDirectory() + // dir without "./" + QTest::newRow("plain-child-chdir") << QString() << ChdirMode::InChild << false; - QCOMPARE(spy.count(), 1); - QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed); + // cross-platform behavior: both OSes search the parent's CWD with "./" + QTest::newRow("prefixed-parent-chdir") << "./" << ChdirMode::InParent << true; - QCOMPARE(spy2.count(), 1); - QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit); + // opposite behaviors: Windows searches the parent's CWD and Unix searches + // the child's with "./" + QTest::newRow("prefixed-child-chdir") << "./" << ChdirMode::InChild << !IsWindows; - QCOMPARE(process.exitStatus(), QProcess::CrashExit); + // Windows searches the parent's CWD without "./" + QTest::newRow("plain-parent-chdir") << QString() << ChdirMode::InParent << IsWindows; } -void tst_QProcess::restartProcessDeadlock_deprecated() +void tst_QProcess::startFromCurrentWorkingDir() { - // The purpose of this test is to detect whether restarting a - // process in the finished() connected slot causes a deadlock - // because of the way QProcessManager uses its locks. - QProcess process; - connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished), - this, &tst_QProcess::restartProcess); - - process.start("testProcessEcho/testProcessEcho"); - - QCOMPARE(process.write("", 1), qlonglong(1)); - QVERIFY(process.waitForFinished(5000)); - - QObject::disconnect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished), nullptr, nullptr); - - QCOMPARE(process.write("", 1), qlonglong(1)); - QVERIFY(process.waitForFinished(5000)); - QCOMPARE(process.exitStatus(), QProcess::NormalExit); - QCOMPARE(process.exitCode(), 0); -} + QFETCH(QString, programPrefix); + QFETCH(ChdirMode, chdirMode); + QFETCH(bool, success); -void tst_QProcess::waitForReadyReadInAReadyReadSlot_deprecated() -{ QProcess process; - connect(&process, &QIODevice::readyRead, this, &tst_QProcess::waitForReadyReadInAReadyReadSlotSlot); - connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished), - this, &tst_QProcess::exitLoopSlot); - bytesAvailable = 0; - - process.start("testProcessEcho/testProcessEcho"); - QVERIFY(process.waitForStarted(5000)); + qRegisterMetaType<QProcess::ProcessError>(); + QSignalSpy errorSpy(&process, &QProcess::errorOccurred); + QVERIFY(errorSpy.isValid()); - QSignalSpy spy(&process, &QProcess::readyRead); - QVERIFY(spy.isValid()); - process.write("foo"); - QTestEventLoop::instance().enterLoop(30); - QVERIFY(!QTestEventLoop::instance().timeout()); + // both the dir name and the executable name + const QString target = QStringLiteral("testProcessNormal"); + process.setProgram(programPrefix + target); - QCOMPARE(spy.count(), 1); +#ifdef Q_OS_UNIX + // Reset PATH, to be sure it doesn't contain . or the empty path. + // We can't do this on Windows because DLLs are searched in PATH + // and Windows always searches "." anyway. + auto restoreEnv = qScopeGuard([old = qgetenv("PATH")] { + qputenv("PATH", old); + }); + qputenv("PATH", "/"); +#endif - process.disconnect(); - QVERIFY(process.waitForFinished(5000)); - QCOMPARE(process.exitStatus(), QProcess::NormalExit); - QCOMPARE(process.exitCode(), 0); - QVERIFY(process.bytesAvailable() > bytesAvailable); -} + switch (chdirMode) { + case ChdirMode::InParent: { + auto restoreCwd = qScopeGuard([old = QDir::currentPath()] { + QDir::setCurrent(old); + }); + QVERIFY(QDir::setCurrent(target)); + process.start(); + break; + } + case ChdirMode::InChild: + process.setWorkingDirectory(target); + Q_FALLTHROUGH(); + case ChdirMode::None: + process.start(); + break; + } -void tst_QProcess::finishProcessBeforeReadingDone_deprecated() -{ - QProcess process; - BlockOnReadStdOut blocker(&process); - QEventLoop loop; - connect(&process, static_cast<QProcessFinishedSignal1>(&QProcess::finished), - &loop, &QEventLoop::quit); - process.start("testProcessOutput/testProcessOutput"); - QVERIFY(process.waitForStarted()); - loop.exec(); - QStringList lines = QString::fromLocal8Bit(process.readAllStandardOutput()).split( - QRegExp(QStringLiteral("[\r\n]")), QString::SkipEmptyParts); - QVERIFY(!lines.isEmpty()); - QCOMPARE(lines.last(), QStringLiteral("10239 -this is a number")); - QCOMPARE(process.exitStatus(), QProcess::NormalExit); - QCOMPARE(process.exitCode(), 0); + QCOMPARE(process.waitForStarted(), success); + QCOMPARE(errorSpy.size(), int(!success)); + if (success) { + QVERIFY(process.waitForFinished()); + } else { + QCOMPARE(process.error(), QProcess::FailedToStart); + } } -#endif - QTEST_MAIN(tst_QProcess) #include "tst_qprocess.moc" |