1//
2// ProcessTest.cpp
3//
4// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "ProcessTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/Process.h"
15#include "Poco/Pipe.h"
16#include "Poco/PipeStream.h"
17#include "Poco/Thread.h"
18#include "Poco/Path.h"
19#include <csignal>
20
21
22using Poco::Process;
23using Poco::ProcessHandle;
24using Poco::Pipe;
25using Poco::PipeInputStream;
26using Poco::PipeOutputStream;
27using Poco::Path;
28
29
30ProcessTest::ProcessTest(const std::string& rName): CppUnit::TestCase(rName)
31{
32}
33
34
35ProcessTest::~ProcessTest()
36{
37}
38
39
40std::string ProcessTest::execName()
41{
42 std::string name = Path(Path::self()).makeParent().toString();
43 name.append("TestApp");
44#if defined(_DEBUG)
45 name.append(1, 'd');
46#endif
47 return name;
48}
49
50
51void ProcessTest::testLaunch()
52{
53 std::string cmd = execName();
54#if defined(_WIN32_WCE)
55- cmd += ".EXE";
56#endif
57 std::vector<std::string> args;
58 args.push_back("arg1");
59 args.push_back("arg2");
60 args.push_back("arg3");
61 ProcessHandle ph = Process::launch(cmd, args);
62 int rc = ph.wait();
63 assertTrue (rc == 3);
64}
65
66
67void ProcessTest::testLaunchRedirectIn()
68{
69#if !defined(_WIN32_WCE)
70 std::vector<std::string> args;
71 args.push_back("-count");
72 Pipe inPipe;
73 ProcessHandle ph = Process::launch(execName(), args, &inPipe, 0, 0);
74 PipeOutputStream ostr(inPipe);
75 ostr << std::string(100, 'x');
76 ostr.close();
77 int rc = ph.wait();
78 assertTrue (rc == 100);
79#endif // !defined(_WIN32_WCE)
80}
81
82
83void ProcessTest::testLaunchRedirectOut()
84{
85#if !defined(_WIN32_WCE)
86 std::vector<std::string> args;
87 args.push_back("-hello");
88 Pipe outPipe;
89 ProcessHandle ph = Process::launch(execName(), args, 0, &outPipe, 0);
90 PipeInputStream istr(outPipe);
91 std::string s;
92 int c = istr.get();
93 while (c != -1) { s += (char) c; c = istr.get(); }
94 assertTrue (s == "Hello, world!");
95 int rc = ph.wait();
96 assertTrue (rc == 1);
97#endif // !defined(_WIN32_WCE)
98}
99
100
101void ProcessTest::testLaunchEnv()
102{
103#if !defined(_WIN32_WCE)
104 std::vector<std::string> args;
105 args.push_back("-env");
106 Pipe outPipe;
107 Process::Env env;
108 env["TESTENV"] = "test";
109 ProcessHandle ph = Process::launch(execName(), args, 0, &outPipe, 0, env);
110 PipeInputStream istr(outPipe);
111 std::string s;
112 int c = istr.get();
113 while (c != -1) { s += (char) c; c = istr.get(); }
114 assertTrue (s == "test");
115 int rc = ph.wait();
116 assertTrue (rc == 0);
117#endif // !defined(_WIN32_WCE)
118}
119
120
121void ProcessTest::testLaunchArgs()
122{
123#if defined (_WIN32) && !defined(_WIN32_WCE)
124 std::vector<std::string> args;
125 args.push_back("-echo-args");
126 args.push_back("simple");
127 args.push_back("with space");
128 args.push_back("with\ttab");
129 args.push_back("with\vverticaltab");
130 // can't test newline here because TestApp -echo-args uses newline to separate the echoed args
131 //args.push_back("with\nnewline");
132 args.push_back("with \" quotes");
133 args.push_back("ends with \"quotes\"");
134 args.push_back("\"starts\" with quotes");
135 args.push_back("\"");
136 args.push_back("\\");
137 args.push_back("c:\\program files\\ends with backslash\\");
138 args.push_back("\"already quoted \\\" \\\\\"");
139 Pipe outPipe;
140 ProcessHandle ph = Process::launch(execName(), args, 0, &outPipe, 0);
141 PipeInputStream istr(outPipe);
142 std::string receivedArg;
143 int c = istr.get();
144 int argNumber = 1;
145 while (c != -1)
146 {
147 if ('\n' == c)
148 {
149 assertTrue (argNumber < args.size());
150 std::string expectedArg = args[argNumber];
151 if (expectedArg.npos != expectedArg.find("already quoted")) {
152 expectedArg = "already quoted \" \\";
153 }
154 assertTrue (receivedArg == expectedArg);
155 ++argNumber;
156 receivedArg = "";
157 }
158 else if ('\r' != c)
159 {
160 receivedArg += (char)c;
161 }
162 c = istr.get();
163 }
164 assertTrue (argNumber == args.size());
165 int rc = ph.wait();
166 assertTrue (rc == args.size());
167#endif // !defined(_WIN32_WCE)
168}
169
170
171void ProcessTest::testIsRunning()
172{
173#if !defined(_WIN32_WCE)
174 std::vector<std::string> args;
175 args.push_back("-count");
176 Pipe inPipe;
177 ProcessHandle ph = Process::launch(execName(), args, &inPipe, 0, 0);
178 Process::PID id = ph.id();
179 assertTrue (Process::isRunning(ph));
180 assertTrue (Process::isRunning(id));
181 PipeOutputStream ostr(inPipe);
182 ostr << std::string(100, 'x');
183 ostr.close();
184 int rc = ph.wait();
185 assertTrue (!Process::isRunning(ph));
186 assertTrue (!Process::isRunning(id));
187#endif // !defined(_WIN32_WCE)
188}
189
190
191void ProcessTest::testIsRunningAllowsForTermination()
192{
193#if !defined(_WIN32_WCE)
194 std::vector<std::string> args;
195 ProcessHandle ph = Process::launch(execName(), args, 0, 0, 0);
196 while (Process::isRunning(ph))
197 Poco::Thread::sleep(100);
198#endif // !defined(_WIN32_WCE)
199}
200
201
202void ProcessTest::testSignalExitCode()
203{
204#if defined(POCO_OS_FAMILY_UNIX)
205 std::vector<std::string> args;
206 args.push_back("-raise-int");
207 ProcessHandle ph = Process::launch(execName(), args, 0, 0, 0);
208 int rc = ph.wait();
209 assertTrue (rc == -SIGINT);
210#endif // defined(POCO_OS_FAMILY_UNIX)
211}
212
213
214void ProcessTest::setUp()
215{
216}
217
218
219void ProcessTest::tearDown()
220{
221}
222
223
224CppUnit::Test* ProcessTest::suite()
225{
226 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ProcessTest");
227
228 CppUnit_addTest(pSuite, ProcessTest, testLaunch);
229 CppUnit_addTest(pSuite, ProcessTest, testLaunchRedirectIn);
230 CppUnit_addTest(pSuite, ProcessTest, testLaunchRedirectOut);
231 CppUnit_addTest(pSuite, ProcessTest, testLaunchEnv);
232 CppUnit_addTest(pSuite, ProcessTest, testLaunchArgs);
233 CppUnit_addTest(pSuite, ProcessTest, testIsRunning);
234 CppUnit_addTest(pSuite, ProcessTest, testIsRunningAllowsForTermination);
235 CppUnit_addTest(pSuite, ProcessTest, testSignalExitCode);
236
237 return pSuite;
238}
239