summaryrefslogtreecommitdiff
path: root/tests/auto/utils/qtcprocess/processtestapp/processtestapp.h
blob: 7fbcabc25dc0f5e978a55d7810a91226ec28cbdc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** 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.
**
****************************************************************************/

#include <functional>

#include <utils/commandline.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>

QT_BEGIN_NAMESPACE
class QProcess;
QT_END_NAMESPACE

namespace Utils { class QtcProcess; }

#define SUB_PROCESS(SubProcessClass)\
class SubProcessClass\
{\
public:\
    static const char *envVar() { return m_envVar; }\
private:\
    SubProcessClass() { registerSubProcess(envVar(), &SubProcessClass::main); }\
    ~SubProcessClass() { unregisterSubProcess(envVar()); }\
    static int main();\
    static constexpr char m_envVar[] = "TST_QTC_PROCESS_" QTC_ASSERT_STRINGIFY(SubProcessClass);\
    friend class ProcessTestApp;\
};\
\
SubProcessClass m_ ## SubProcessClass

class ProcessTestApp
{
public:
    using SubProcessMain = std::function<int ()>;

    static void invokeSubProcess();

    // Many tests inside tst_qtcprocess need to start a new subprocess with custom code.
    // In order to simplify things we produce just one separate executable - processtestapp.
    // We embed all our custom subprocesses in processtestapp and enclose them in separate
    // classes. We select desired process to run by setting the relevant environment variable.
    // Test classes are defined by the SUB_PROCESS macro. The macro defines a class
    // alongside of the corresponding environment variable which is set prior to the execution
    // of the subprocess. The following subprocess classes are defined:

    SUB_PROCESS(SimpleTest);
    SUB_PROCESS(ExitCode);
    SUB_PROCESS(RunBlockingStdOut);
    SUB_PROCESS(LineCallback);
    SUB_PROCESS(StandardOutputAndErrorWriter);
    SUB_PROCESS(ChannelForwarding);
    SUB_PROCESS(BlockingProcess);
    SUB_PROCESS(Crash);
    SUB_PROCESS(CrashAfterOneSecond);
    SUB_PROCESS(RecursiveCrashingProcess);
    SUB_PROCESS(RecursiveBlockingProcess);

    // In order to get a value associated with the certain subprocess use SubProcessClass::envVar().
    // The classes above define different custom executables. Inside invokeSubProcess(), called
    // by processtestapp, we are detecting if one of these variables is set and invoke a respective
    // custom executable code directly. The exit code of the process is reported to the caller
    // by the return value of SubProcessClass::main().

private:
    ProcessTestApp();

    static void registerSubProcess(const char *envVar, const SubProcessMain &main);
    static void unregisterSubProcess(const char *envVar);
};

class SubProcessConfig
{
public:
    SubProcessConfig(const char *envVar, const QString &envVal);
    void setupSubProcess(Utils::QtcProcess *subProcess);
    void setupSubProcess(QProcess *subProcess);

    static void setPathToProcessTestApp(const QString &path);

private:
    const Utils::Environment m_environment;
};

static const char s_simpleTestData[] = "Test process successfully executed.";
static const char s_runBlockingStdOutSubProcessMagicWord[] = "42";

// Expect ending lines detected at '|':
static const char s_lineCallbackData[] =
       "This is the first line\r\n|"
       "Here comes the second one\r\n|"
       "And a line without LF\n|"
       "Rebasing (1/10)\r| <delay> Rebasing (2/10)\r| <delay> ...\r\n|"
       "And no end";

static const char s_outputData[] = "This is the output message.";
static const char s_errorData[] = "This is the error message.";

enum class BlockType {
    EndlessLoop,
    InfiniteSleep,
    MutexDeadlock,
    EventLoop
};

static const int s_crashCode = 123;
static const char s_leafProcessStarted[] = "Leaf process started";
static const char s_leafProcessTerminated[] = "Leaf process terminated";

Q_DECLARE_METATYPE(BlockType)